using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Resources;
using ObjectLib;
using EngMATLib;
using FftLib;
using BmgNet;
using StaticUtility;

namespace ObjectParser
{
	/// <summary>
	/// The main form for the ObjectParser application.
	/// </summary>
	public class FormParse : System.Windows.Forms.Form, IFormParse
	{
		#region Form Component Declarations
		public OpenFileDialog OfdBatch;
		public OpenFileDialog OfdNewProjectFromImage;
		public SaveFileDialog SfdSaveProject;
		public OpenFileDialog OfdBatchFix1;
		public OpenFileDialog OfdImportAttributesOpd;
		public OpenFileDialog OfdImportAttributesTxt;
		public OpenFileDialog OfdFilter;
		private System.Windows.Forms.MainMenu menuProj;
		private System.Windows.Forms.MenuItem mFileOpenProj;
		private System.Windows.Forms.MenuItem mFileNewProj;
		private System.Windows.Forms.MenuItem mFile;
		private System.Windows.Forms.MenuItem mTool;
		private System.Windows.Forms.MenuItem mView;
		private System.Windows.Forms.MenuItem mProj;
		private System.Windows.Forms.MenuItem mOptions;
        private System.Windows.Forms.MenuItem mOptionsColors;
		private System.Windows.Forms.MenuItem mOpsColsPolyLine;
		private System.Windows.Forms.MenuItem mOpsColsCurObj;
        private System.Windows.Forms.MenuItem mOpsColsOtherObj;
		private System.Windows.Forms.MenuItem menuItem1;
		private System.Windows.Forms.MenuItem mProjectClose;
        private System.Windows.Forms.MenuItem mOptionsAlphas;
		private System.Windows.Forms.MenuItem mOpsAlphaPolyLine;
		private System.Windows.Forms.MenuItem mOpsAlphaCurObj;
		private System.Windows.Forms.MenuItem mOpsAlphaOtherObj;
		private System.Windows.Forms.MenuItem menuItem3;
		public System.Windows.Forms.MenuItem mNearNeighbor;
		public System.Windows.Forms.MenuItem mBilinear;
		public System.Windows.Forms.MenuItem mSave;
		private System.Windows.Forms.MenuItem mSaveAs;
		private System.Windows.Forms.OpenFileDialog ofdOpenProj;
        private System.Windows.Forms.MenuItem mHelp;
		private System.Windows.Forms.SaveFileDialog sfdOutput;
		private System.Windows.Forms.MenuItem mCopyZoomed;
		private System.Windows.Forms.MenuItem menuItem9;
		private System.Windows.Forms.MenuItem mUndo;
		private System.Windows.Forms.MenuItem mRedo;
		private System.Windows.Forms.MenuItem mResetZoom;
		private System.Windows.Forms.MenuItem mEdit;
		private System.Windows.Forms.MenuItem mOpsColsNonObj;
		private System.Windows.Forms.MenuItem mOpsAlphaNonObj;
		private System.Windows.Forms.MenuItem menuItem2;
		private System.Windows.Forms.MenuItem mTutorial;
		private System.Windows.Forms.MenuItem mHelpKeyMouse;
		private System.Windows.Forms.MenuItem mSetDisplay;
        private System.Windows.Forms.MenuItem menuItem7;
        private System.ComponentModel.IContainer components;
		private System.Windows.Forms.MenuItem mMaximize;
		private System.Windows.Forms.MenuItem mCopyActiveObj;
		private System.Windows.Forms.MenuItem mCopyBgActiveObj;
		private System.Windows.Forms.MenuItem mCopyActiveObjWithBg;
		private System.Windows.Forms.MenuItem menuItem13;
		private System.Windows.Forms.MenuItem mResetPixels;
		private System.Windows.Forms.MenuItem mCategorize;
		private System.Windows.Forms.MenuItem menuItem8;
		private System.Windows.Forms.MenuItem mBatch;
		private System.Windows.Forms.MenuItem mFix1;
		private System.Windows.Forms.MenuItem mWilsonOut1;
		private System.Windows.Forms.MenuItem mSetCore;
        private System.Windows.Forms.MenuItem mBatchBinaryMaskOut;
		private System.Windows.Forms.MenuItem mImportAttributes;
		private System.Windows.Forms.MenuItem menuItem14;
		private System.Windows.Forms.MenuItem mCategorizationValues;
		private System.Windows.Forms.MenuItem mImageSettings;
		private System.Windows.Forms.MenuItem menuItem15;
		private System.Windows.Forms.MenuItem menuItem17;
		private System.Windows.Forms.MenuItem mFindBadVert;
		public System.Windows.Forms.TreeView Tv;
		private System.Windows.Forms.Panel panelMain;
		private System.Windows.Forms.ContextMenu contextMenu1;
		private System.Windows.Forms.MenuItem mNewSubCat;
		private System.Windows.Forms.MenuItem mNewSubObj;
		private System.Windows.Forms.MenuItem menuItem19;
		private System.Windows.Forms.MenuItem mCut;
		private System.Windows.Forms.MenuItem mPaste;
		private System.Windows.Forms.MenuItem mDelete;
        private System.Windows.Forms.MenuItem menuItem20;
		private System.Windows.Forms.ToolTip toolTip1;
		private System.Windows.Forms.MenuItem mElimRedundant;
		private System.Windows.Forms.MenuItem mSeriesForward;
		private System.Windows.Forms.MenuItem mSeriesBackward;
        private System.Windows.Forms.MenuItem menuItem18;
        private System.Windows.Forms.MenuItem mElimEmpty;
        private System.Windows.Forms.MenuItem mTidyOwnedEdges;
		private System.Windows.Forms.Panel panelLeft;
		private System.Windows.Forms.Splitter splitMainVert;
		private System.Windows.Forms.Panel panelFull;
		private System.Windows.Forms.Panel panelBottom;
		private System.Windows.Forms.StatusBar statusBar1;
		private System.Windows.Forms.Panel panelRight;
		private System.Windows.Forms.Splitter splitRightHor;
		public PbViewer PbRibbon;
		public System.Windows.Forms.PictureBox Pb;
        private System.Windows.Forms.MenuItem cmViewEdgePoints;
        private System.Windows.Forms.MenuItem mBatchEdgesOut;
        private System.Windows.Forms.MenuItem mCopyRibbons;
		public System.Windows.Forms.Button bViewAll;
		public System.Windows.Forms.Button bViewInactiveCat;
		public System.Windows.Forms.Button bViewActiveCat;
		public System.Windows.Forms.Button bViewEdges;
		public System.Windows.Forms.Button bViewPoly;
		public System.Windows.Forms.Button bViewActiveCircle;
		public System.Windows.Forms.Button bLinkMode;
		private System.Windows.Forms.MenuItem mJumpLastPath;
		private System.Windows.Forms.MenuItem mJumpNextPath;
		private System.Windows.Forms.MenuItem menuItem5;
		private System.Windows.Forms.MenuItem mLogGabor;
		private System.Windows.Forms.MenuItem mUnswallowAll;
		private System.Windows.Forms.MenuItem menuItem16;
        private System.Windows.Forms.MenuItem mViewNan;
		private System.Windows.Forms.MenuItem mMatlabSpines;
		private System.Windows.Forms.MenuItem mCreateShowoff;
		private System.Windows.Forms.MenuItem mCategorizeContours;
		private System.Windows.Forms.MenuItem menuItem22;
		private System.Windows.Forms.MenuItem mBatchExportContourRibbonsFull;
		private System.Windows.Forms.MenuItem mBatchExportBoundaryRibbonsFull;
        private System.Windows.Forms.MenuItem menuItem25;
		public System.Windows.Forms.Button bViewContours;
		public System.Windows.Forms.Button bViewXjunc;
		private System.Windows.Forms.ImageList imViewXjunc;
		private System.Windows.Forms.ImageList imViewTjunc;
		public System.Windows.Forms.Button bViewTjunc;
		private System.Windows.Forms.ImageList imViewPoly;
		private System.Windows.Forms.ImageList imLinkMode;
		private System.Windows.Forms.ImageList imViewVertices;
		private System.Windows.Forms.ImageList imViewInactiveCat;
		private System.Windows.Forms.ImageList imViewActiveCat;
		private System.Windows.Forms.ImageList imViewAll;
		private System.Windows.Forms.ImageList imToolContour;
		private System.Windows.Forms.ImageList imToolPoly;
		private System.Windows.Forms.ImageList imViewEdge;
		private System.Windows.Forms.ImageList imViewContour;
		private System.Windows.Forms.ImageList imViewCircle;
		public System.Windows.Forms.Button bViewVertices;
		private System.Windows.Forms.MenuItem mImportCameraSettings;
		private System.Windows.Forms.OpenFileDialog OfdCameraSettings;
		private System.Windows.Forms.OpenFileDialog OfdOpenBatch;
        private MenuItem mExportCircles;
        private MenuItem mAbout;
        private MenuItem mExportCircles_v2;
        private MenuItem mBatchSimpleHist;
        private MenuItem mBatchFullObsRibbons;
        private MenuItem mBatchExportRoiPatches;
        private MenuItem mBatchFix2;
        private MenuItem mBatchBinaryToXml;
        private MenuItem mNewSubPoly;
        private MenuItem mNewSubContour;
        private MenuItem mNewCircle;
        public PictureBox pbTool;
        private ImageList imTool;
        private MenuItem mColor;
        private MenuItem menuItem4;
        private MenuItem mColorRevert;
        private MenuItem mPaintShadowsYellow;
        private OpenFileDialog OfdBatchFix;
        private MenuItem mNewPixScope;
        private MenuItem mMakeThumbnails;
		private System.Windows.Forms.MenuItem menuItem11;
		#endregion
		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
            this.components = new System.ComponentModel.Container();
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormParse));
            this.menuProj = new System.Windows.Forms.MainMenu(this.components);
            this.mFile = new System.Windows.Forms.MenuItem();
            this.mFileNewProj = new System.Windows.Forms.MenuItem();
            this.mFileOpenProj = new System.Windows.Forms.MenuItem();
            this.menuItem8 = new System.Windows.Forms.MenuItem();
            this.mBatch = new System.Windows.Forms.MenuItem();
            this.mFix1 = new System.Windows.Forms.MenuItem();
            this.mImportAttributes = new System.Windows.Forms.MenuItem();
            this.mImportCameraSettings = new System.Windows.Forms.MenuItem();
            this.mBatchFix2 = new System.Windows.Forms.MenuItem();
            this.mPaintShadowsYellow = new System.Windows.Forms.MenuItem();
            this.menuItem14 = new System.Windows.Forms.MenuItem();
            this.mWilsonOut1 = new System.Windows.Forms.MenuItem();
            this.mBatchBinaryMaskOut = new System.Windows.Forms.MenuItem();
            this.mBatchEdgesOut = new System.Windows.Forms.MenuItem();
            this.mCreateShowoff = new System.Windows.Forms.MenuItem();
            this.mBatchBinaryToXml = new System.Windows.Forms.MenuItem();
            this.menuItem15 = new System.Windows.Forms.MenuItem();
            this.mBatchExportRoiPatches = new System.Windows.Forms.MenuItem();
            this.mBatchSimpleHist = new System.Windows.Forms.MenuItem();
            this.mExportCircles_v2 = new System.Windows.Forms.MenuItem();
            this.mExportCircles = new System.Windows.Forms.MenuItem();
            this.mMatlabSpines = new System.Windows.Forms.MenuItem();
            this.menuItem22 = new System.Windows.Forms.MenuItem();
            this.mBatchExportContourRibbonsFull = new System.Windows.Forms.MenuItem();
            this.mBatchExportBoundaryRibbonsFull = new System.Windows.Forms.MenuItem();
            this.mBatchFullObsRibbons = new System.Windows.Forms.MenuItem();
            this.menuItem25 = new System.Windows.Forms.MenuItem();
            this.mMakeThumbnails = new System.Windows.Forms.MenuItem();
            this.mProj = new System.Windows.Forms.MenuItem();
            this.mSetDisplay = new System.Windows.Forms.MenuItem();
            this.mSetCore = new System.Windows.Forms.MenuItem();
            this.menuItem11 = new System.Windows.Forms.MenuItem();
            this.mCategorizationValues = new System.Windows.Forms.MenuItem();
            this.mImageSettings = new System.Windows.Forms.MenuItem();
            this.menuItem7 = new System.Windows.Forms.MenuItem();
            this.mSave = new System.Windows.Forms.MenuItem();
            this.mSaveAs = new System.Windows.Forms.MenuItem();
            this.menuItem1 = new System.Windows.Forms.MenuItem();
            this.mProjectClose = new System.Windows.Forms.MenuItem();
            this.mEdit = new System.Windows.Forms.MenuItem();
            this.mCopyZoomed = new System.Windows.Forms.MenuItem();
            this.mCopyActiveObj = new System.Windows.Forms.MenuItem();
            this.mCopyActiveObjWithBg = new System.Windows.Forms.MenuItem();
            this.mCopyBgActiveObj = new System.Windows.Forms.MenuItem();
            this.menuItem9 = new System.Windows.Forms.MenuItem();
            this.mUndo = new System.Windows.Forms.MenuItem();
            this.mRedo = new System.Windows.Forms.MenuItem();
            this.menuItem17 = new System.Windows.Forms.MenuItem();
            this.mCopyRibbons = new System.Windows.Forms.MenuItem();
            this.mView = new System.Windows.Forms.MenuItem();
            this.mResetZoom = new System.Windows.Forms.MenuItem();
            this.mMaximize = new System.Windows.Forms.MenuItem();
            this.menuItem16 = new System.Windows.Forms.MenuItem();
            this.mViewNan = new System.Windows.Forms.MenuItem();
            this.mTool = new System.Windows.Forms.MenuItem();
            this.mJumpLastPath = new System.Windows.Forms.MenuItem();
            this.mJumpNextPath = new System.Windows.Forms.MenuItem();
            this.menuItem18 = new System.Windows.Forms.MenuItem();
            this.mSeriesForward = new System.Windows.Forms.MenuItem();
            this.mSeriesBackward = new System.Windows.Forms.MenuItem();
            this.menuItem2 = new System.Windows.Forms.MenuItem();
            this.mCategorize = new System.Windows.Forms.MenuItem();
            this.mCategorizeContours = new System.Windows.Forms.MenuItem();
            this.menuItem13 = new System.Windows.Forms.MenuItem();
            this.mResetPixels = new System.Windows.Forms.MenuItem();
            this.mFindBadVert = new System.Windows.Forms.MenuItem();
            this.mElimRedundant = new System.Windows.Forms.MenuItem();
            this.mElimEmpty = new System.Windows.Forms.MenuItem();
            this.mTidyOwnedEdges = new System.Windows.Forms.MenuItem();
            this.mUnswallowAll = new System.Windows.Forms.MenuItem();
            this.menuItem5 = new System.Windows.Forms.MenuItem();
            this.mLogGabor = new System.Windows.Forms.MenuItem();
            this.mOptions = new System.Windows.Forms.MenuItem();
            this.mOptionsColors = new System.Windows.Forms.MenuItem();
            this.mOpsColsPolyLine = new System.Windows.Forms.MenuItem();
            this.mOpsColsCurObj = new System.Windows.Forms.MenuItem();
            this.mOpsColsOtherObj = new System.Windows.Forms.MenuItem();
            this.mOpsColsNonObj = new System.Windows.Forms.MenuItem();
            this.mOptionsAlphas = new System.Windows.Forms.MenuItem();
            this.mOpsAlphaPolyLine = new System.Windows.Forms.MenuItem();
            this.mOpsAlphaCurObj = new System.Windows.Forms.MenuItem();
            this.mOpsAlphaOtherObj = new System.Windows.Forms.MenuItem();
            this.mOpsAlphaNonObj = new System.Windows.Forms.MenuItem();
            this.menuItem3 = new System.Windows.Forms.MenuItem();
            this.mNearNeighbor = new System.Windows.Forms.MenuItem();
            this.mBilinear = new System.Windows.Forms.MenuItem();
            this.mHelp = new System.Windows.Forms.MenuItem();
            this.mTutorial = new System.Windows.Forms.MenuItem();
            this.mHelpKeyMouse = new System.Windows.Forms.MenuItem();
            this.mAbout = new System.Windows.Forms.MenuItem();
            this.ofdOpenProj = new System.Windows.Forms.OpenFileDialog();
            this.sfdOutput = new System.Windows.Forms.SaveFileDialog();
            this.Tv = new System.Windows.Forms.TreeView();
            this.contextMenu1 = new System.Windows.Forms.ContextMenu();
            this.mNewPixScope = new System.Windows.Forms.MenuItem();
            this.mNewSubCat = new System.Windows.Forms.MenuItem();
            this.mNewSubObj = new System.Windows.Forms.MenuItem();
            this.mNewSubPoly = new System.Windows.Forms.MenuItem();
            this.mNewSubContour = new System.Windows.Forms.MenuItem();
            this.mNewCircle = new System.Windows.Forms.MenuItem();
            this.menuItem19 = new System.Windows.Forms.MenuItem();
            this.mColor = new System.Windows.Forms.MenuItem();
            this.mColorRevert = new System.Windows.Forms.MenuItem();
            this.menuItem4 = new System.Windows.Forms.MenuItem();
            this.mCut = new System.Windows.Forms.MenuItem();
            this.mPaste = new System.Windows.Forms.MenuItem();
            this.mDelete = new System.Windows.Forms.MenuItem();
            this.menuItem20 = new System.Windows.Forms.MenuItem();
            this.cmViewEdgePoints = new System.Windows.Forms.MenuItem();
            this.panelMain = new System.Windows.Forms.Panel();
            this.panelRight = new System.Windows.Forms.Panel();
            this.splitRightHor = new System.Windows.Forms.Splitter();
            this.PbRibbon = new ObjectParser.PbViewer();
            this.Pb = new System.Windows.Forms.PictureBox();
            this.splitMainVert = new System.Windows.Forms.Splitter();
            this.panelLeft = new System.Windows.Forms.Panel();
            this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
            this.bViewAll = new System.Windows.Forms.Button();
            this.imViewAll = new System.Windows.Forms.ImageList(this.components);
            this.bViewInactiveCat = new System.Windows.Forms.Button();
            this.imViewInactiveCat = new System.Windows.Forms.ImageList(this.components);
            this.bViewActiveCat = new System.Windows.Forms.Button();
            this.imViewActiveCat = new System.Windows.Forms.ImageList(this.components);
            this.bViewEdges = new System.Windows.Forms.Button();
            this.imViewEdge = new System.Windows.Forms.ImageList(this.components);
            this.bViewPoly = new System.Windows.Forms.Button();
            this.imViewPoly = new System.Windows.Forms.ImageList(this.components);
            this.bViewActiveCircle = new System.Windows.Forms.Button();
            this.imViewCircle = new System.Windows.Forms.ImageList(this.components);
            this.bLinkMode = new System.Windows.Forms.Button();
            this.imLinkMode = new System.Windows.Forms.ImageList(this.components);
            this.bViewContours = new System.Windows.Forms.Button();
            this.imViewContour = new System.Windows.Forms.ImageList(this.components);
            this.bViewXjunc = new System.Windows.Forms.Button();
            this.imViewXjunc = new System.Windows.Forms.ImageList(this.components);
            this.bViewTjunc = new System.Windows.Forms.Button();
            this.imViewTjunc = new System.Windows.Forms.ImageList(this.components);
            this.bViewVertices = new System.Windows.Forms.Button();
            this.imViewVertices = new System.Windows.Forms.ImageList(this.components);
            this.pbTool = new System.Windows.Forms.PictureBox();
            this.imToolPoly = new System.Windows.Forms.ImageList(this.components);
            this.imToolContour = new System.Windows.Forms.ImageList(this.components);
            this.panelFull = new System.Windows.Forms.Panel();
            this.panelBottom = new System.Windows.Forms.Panel();
            this.statusBar1 = new System.Windows.Forms.StatusBar();
            this.OfdCameraSettings = new System.Windows.Forms.OpenFileDialog();
            this.OfdOpenBatch = new System.Windows.Forms.OpenFileDialog();
            this.imTool = new System.Windows.Forms.ImageList(this.components);
            this.OfdBatchFix = new System.Windows.Forms.OpenFileDialog();
            this.panelMain.SuspendLayout();
            this.panelRight.SuspendLayout();
            ((System.ComponentModel.ISupportInitialize)(this.PbRibbon)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.Pb)).BeginInit();
            this.panelLeft.SuspendLayout();
            ((System.ComponentModel.ISupportInitialize)(this.pbTool)).BeginInit();
            this.panelFull.SuspendLayout();
            this.panelBottom.SuspendLayout();
            this.SuspendLayout();
            // 
            // menuProj
            // 
            this.menuProj.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mFile,
            this.mProj,
            this.mEdit,
            this.mView,
            this.mTool,
            this.mOptions,
            this.mHelp});
            // 
            // mFile
            // 
            this.mFile.Index = 0;
            this.mFile.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mFileNewProj,
            this.mFileOpenProj,
            this.menuItem8,
            this.mBatch});
            this.mFile.Text = "File";
            // 
            // mFileNewProj
            // 
            this.mFileNewProj.Index = 0;
            this.mFileNewProj.Text = "New Project From Core Image...";
            this.mFileNewProj.Click += new System.EventHandler(this.mFileNewProj_Click);
            // 
            // mFileOpenProj
            // 
            this.mFileOpenProj.Index = 1;
            this.mFileOpenProj.Text = "Open Project...";
            this.mFileOpenProj.Click += new System.EventHandler(this.mFileOpenProj_Click);
            // 
            // menuItem8
            // 
            this.menuItem8.Index = 2;
            this.menuItem8.Text = "-";
            // 
            // mBatch
            // 
            this.mBatch.Index = 3;
            this.mBatch.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mFix1,
            this.mImportAttributes,
            this.mImportCameraSettings,
            this.mBatchFix2,
            this.mPaintShadowsYellow,
            this.menuItem14,
            this.mWilsonOut1,
            this.mBatchBinaryMaskOut,
            this.mBatchEdgesOut,
            this.mCreateShowoff,
            this.mBatchBinaryToXml,
            this.menuItem15,
            this.mBatchExportRoiPatches,
            this.mBatchSimpleHist,
            this.mExportCircles_v2,
            this.mExportCircles,
            this.mMatlabSpines,
            this.menuItem22,
            this.mBatchExportContourRibbonsFull,
            this.mBatchExportBoundaryRibbonsFull,
            this.mBatchFullObsRibbons,
            this.menuItem25,
            this.mMakeThumbnails});
            this.mBatch.Text = "Batch";
            // 
            // mFix1
            // 
            this.mFix1.Index = 0;
            this.mFix1.Text = "Fix1...";
            this.mFix1.Click += new System.EventHandler(this.mFix1_Click);
            // 
            // mImportAttributes
            // 
            this.mImportAttributes.Index = 1;
            this.mImportAttributes.Text = "Import Attributes...";
            this.mImportAttributes.Click += new System.EventHandler(this.mImportAttributes_Click);
            // 
            // mImportCameraSettings
            // 
            this.mImportCameraSettings.Index = 2;
            this.mImportCameraSettings.Text = "Import Camera Settings...";
            this.mImportCameraSettings.Click += new System.EventHandler(this.mImportCameraSettings_Click);
            // 
            // mBatchFix2
            // 
            this.mBatchFix2.Index = 3;
            this.mBatchFix2.Text = "Fix2...";
            this.mBatchFix2.Click += new System.EventHandler(this.mBatchFix2_Click);
            // 
            // mPaintShadowsYellow
            // 
            this.mPaintShadowsYellow.Index = 4;
            this.mPaintShadowsYellow.Text = "Paint Shadows Yellow...";
            this.mPaintShadowsYellow.Click += new System.EventHandler(this.mPaintShadowsYellow_Click);
            // 
            // menuItem14
            // 
            this.menuItem14.Index = 5;
            this.menuItem14.Text = "-";
            // 
            // mWilsonOut1
            // 
            this.mWilsonOut1.Index = 6;
            this.mWilsonOut1.Text = "Wilson Output 1";
            this.mWilsonOut1.Click += new System.EventHandler(this.mWilsonOut1_Click);
            // 
            // mBatchBinaryMaskOut
            // 
            this.mBatchBinaryMaskOut.Index = 7;
            this.mBatchBinaryMaskOut.Text = "Binary Mask Output...";
            this.mBatchBinaryMaskOut.Click += new System.EventHandler(this.mBatchBinaryMaskOut_Click);
            // 
            // mBatchEdgesOut
            // 
            this.mBatchEdgesOut.Index = 8;
            this.mBatchEdgesOut.Text = "Edge Output...";
            this.mBatchEdgesOut.Click += new System.EventHandler(this.mBatchEdgesOut_Click);
            // 
            // mCreateShowoff
            // 
            this.mCreateShowoff.Index = 9;
            this.mCreateShowoff.Text = "Create Showoff Images...";
            this.mCreateShowoff.Click += new System.EventHandler(this.mCreateShowoff_Click);
            // 
            // mBatchBinaryToXml
            // 
            this.mBatchBinaryToXml.Index = 10;
            this.mBatchBinaryToXml.Text = "Binary to Xml...";
            this.mBatchBinaryToXml.Click += new System.EventHandler(this.mBatchBinaryToXml_Click);
            // 
            // menuItem15
            // 
            this.menuItem15.Index = 11;
            this.menuItem15.Text = "-";
            // 
            // mBatchExportRoiPatches
            // 
            this.mBatchExportRoiPatches.Index = 12;
            this.mBatchExportRoiPatches.Text = "Export ROI patches to Matlab";
            this.mBatchExportRoiPatches.Click += new System.EventHandler(this.mBatchExportRoiPatches_Click);
            // 
            // mBatchSimpleHist
            // 
            this.mBatchSimpleHist.Index = 13;
            this.mBatchSimpleHist.Text = "Export Simple Histograms To Matlab";
            this.mBatchSimpleHist.Click += new System.EventHandler(this.mBatchExportBasicHists);
            // 
            // mExportCircles_v2
            // 
            this.mExportCircles_v2.Index = 14;
            this.mExportCircles_v2.Text = "Export Circles To Matlab v2...";
            this.mExportCircles_v2.Click += new System.EventHandler(this.mBatchExportCircles2_Click);
            // 
            // mExportCircles
            // 
            this.mExportCircles.Index = 15;
            this.mExportCircles.Text = "Export Circles To Matlab...";
            this.mExportCircles.Click += new System.EventHandler(this.mBatchExportCircles_Click);
            // 
            // mMatlabSpines
            // 
            this.mMatlabSpines.Index = 16;
            this.mMatlabSpines.Text = "Export Spines To Matlab...";
            this.mMatlabSpines.Click += new System.EventHandler(this.mMatlabSpines_Click);
            // 
            // menuItem22
            // 
            this.menuItem22.Index = 17;
            this.menuItem22.Text = "-";
            // 
            // mBatchExportContourRibbonsFull
            // 
            this.mBatchExportContourRibbonsFull.Index = 18;
            this.mBatchExportContourRibbonsFull.Text = "Export Full Contour Ribbons To Matlab...";
            this.mBatchExportContourRibbonsFull.Click += new System.EventHandler(this.mBatchExportContourRibbonsFull_Click);
            // 
            // mBatchExportBoundaryRibbonsFull
            // 
            this.mBatchExportBoundaryRibbonsFull.Index = 19;
            this.mBatchExportBoundaryRibbonsFull.Text = "Export Full Boundary Ribbons To Matlab...";
            this.mBatchExportBoundaryRibbonsFull.Click += new System.EventHandler(this.mBatchExportBoundaryRibbonsFull_Click);
            // 
            // mBatchFullObsRibbons
            // 
            this.mBatchFullObsRibbons.Index = 20;
            this.mBatchFullObsRibbons.Text = "Export Full Obs Ribbons To Matlab...";
            this.mBatchFullObsRibbons.Click += new System.EventHandler(this.mBatchFullObsRibbons_Click);
            // 
            // menuItem25
            // 
            this.menuItem25.Index = 21;
            this.menuItem25.Text = "-";
            // 
            // mMakeThumbnails
            // 
            this.mMakeThumbnails.Index = 22;
            this.mMakeThumbnails.Text = "Make Thumbnails";
            this.mMakeThumbnails.Click += new System.EventHandler(this.mMakeThumbnails_Click);
            // 
            // mProj
            // 
            this.mProj.Index = 1;
            this.mProj.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mSetDisplay,
            this.mSetCore,
            this.menuItem11,
            this.mCategorizationValues,
            this.mImageSettings,
            this.menuItem7,
            this.mSave,
            this.mSaveAs,
            this.menuItem1,
            this.mProjectClose});
            this.mProj.Text = "Project";
            // 
            // mSetDisplay
            // 
            this.mSetDisplay.Index = 0;
            this.mSetDisplay.Text = "Set Display Image ...";
            this.mSetDisplay.Click += new System.EventHandler(this.mSetDisplay_Click);
            // 
            // mSetCore
            // 
            this.mSetCore.Index = 1;
            this.mSetCore.Text = "Set Core Image ...";
            this.mSetCore.Click += new System.EventHandler(this.mSetCore_Click);
            // 
            // menuItem11
            // 
            this.menuItem11.Index = 2;
            this.menuItem11.Text = "-";
            // 
            // mCategorizationValues
            // 
            this.mCategorizationValues.Index = 3;
            this.mCategorizationValues.Text = "Categorization Values ...";
            this.mCategorizationValues.Click += new System.EventHandler(this.mCategorizationValues_Click);
            // 
            // mImageSettings
            // 
            this.mImageSettings.Index = 4;
            this.mImageSettings.Text = "Image Settings ...";
            this.mImageSettings.Click += new System.EventHandler(this.mImageSettings_Click);
            // 
            // menuItem7
            // 
            this.menuItem7.Index = 5;
            this.menuItem7.Text = "-";
            // 
            // mSave
            // 
            this.mSave.Index = 6;
            this.mSave.Text = "Save";
            this.mSave.Click += new System.EventHandler(this.mSave_Click);
            // 
            // mSaveAs
            // 
            this.mSaveAs.Index = 7;
            this.mSaveAs.Text = "Save As ...";
            this.mSaveAs.Click += new System.EventHandler(this.mSaveAs_Click);
            // 
            // menuItem1
            // 
            this.menuItem1.Index = 8;
            this.menuItem1.Text = "-";
            // 
            // mProjectClose
            // 
            this.mProjectClose.Index = 9;
            this.mProjectClose.Text = "Close Project";
            this.mProjectClose.Click += new System.EventHandler(this.mProjectClose_Click);
            // 
            // mEdit
            // 
            this.mEdit.Index = 2;
            this.mEdit.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mCopyZoomed,
            this.mCopyActiveObj,
            this.mCopyActiveObjWithBg,
            this.mCopyBgActiveObj,
            this.menuItem9,
            this.mUndo,
            this.mRedo,
            this.menuItem17,
            this.mCopyRibbons});
            this.mEdit.Text = "Edit";
            // 
            // mCopyZoomed
            // 
            this.mCopyZoomed.Index = 0;
            this.mCopyZoomed.Text = "Copy Zoomed Region";
            this.mCopyZoomed.Click += new System.EventHandler(this.mCopyZoomed_Click);
            // 
            // mCopyActiveObj
            // 
            this.mCopyActiveObj.Index = 1;
            this.mCopyActiveObj.Text = "Copy Active Object Without Background";
            this.mCopyActiveObj.Click += new System.EventHandler(this.mCopyActiveObj_Click);
            // 
            // mCopyActiveObjWithBg
            // 
            this.mCopyActiveObjWithBg.Index = 2;
            this.mCopyActiveObjWithBg.Text = "Copy Active Object With Background";
            this.mCopyActiveObjWithBg.Click += new System.EventHandler(this.mCopyActiveObjWithBg_Click);
            // 
            // mCopyBgActiveObj
            // 
            this.mCopyBgActiveObj.Index = 3;
            this.mCopyBgActiveObj.Text = "Copy Active Object Background Only";
            this.mCopyBgActiveObj.Click += new System.EventHandler(this.mCopyBgActiveObj_Click);
            // 
            // menuItem9
            // 
            this.menuItem9.Index = 4;
            this.menuItem9.Text = "-";
            // 
            // mUndo
            // 
            this.mUndo.Index = 5;
            this.mUndo.Shortcut = System.Windows.Forms.Shortcut.CtrlZ;
            this.mUndo.Text = "Undo";
            this.mUndo.Click += new System.EventHandler(this.mUndo_Click);
            // 
            // mRedo
            // 
            this.mRedo.Index = 6;
            this.mRedo.Shortcut = System.Windows.Forms.Shortcut.CtrlY;
            this.mRedo.Text = "Redo";
            this.mRedo.Click += new System.EventHandler(this.mRedo_Click);
            // 
            // menuItem17
            // 
            this.menuItem17.Index = 7;
            this.menuItem17.Text = "-";
            // 
            // mCopyRibbons
            // 
            this.mCopyRibbons.Index = 8;
            this.mCopyRibbons.Text = "Copy Active Surfaces (Ribbons)";
            this.mCopyRibbons.Click += new System.EventHandler(this.mCopyRibbons_Click);
            // 
            // mView
            // 
            this.mView.Index = 3;
            this.mView.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mResetZoom,
            this.mMaximize,
            this.menuItem16,
            this.mViewNan});
            this.mView.Text = "View";
            // 
            // mResetZoom
            // 
            this.mResetZoom.Index = 0;
            this.mResetZoom.Text = "Reset Zoom";
            this.mResetZoom.Click += new System.EventHandler(this.mResetZoom_Click);
            // 
            // mMaximize
            // 
            this.mMaximize.Index = 1;
            this.mMaximize.Shortcut = System.Windows.Forms.Shortcut.CtrlM;
            this.mMaximize.Text = "Maximize Window";
            this.mMaximize.Click += new System.EventHandler(this.mMaximize_Click);
            // 
            // menuItem16
            // 
            this.menuItem16.Index = 2;
            this.menuItem16.Text = "-";
            // 
            // mViewNan
            // 
            this.mViewNan.Index = 3;
            this.mViewNan.Text = "NaN Pixels";
            this.mViewNan.Click += new System.EventHandler(this.mViewNan_Click);
            // 
            // mTool
            // 
            this.mTool.Index = 4;
            this.mTool.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mJumpLastPath,
            this.mJumpNextPath,
            this.menuItem18,
            this.mSeriesForward,
            this.mSeriesBackward,
            this.menuItem2,
            this.mCategorize,
            this.mCategorizeContours,
            this.menuItem13,
            this.mResetPixels,
            this.mFindBadVert,
            this.mElimRedundant,
            this.mElimEmpty,
            this.mTidyOwnedEdges,
            this.mUnswallowAll,
            this.menuItem5,
            this.mLogGabor});
            this.mTool.Text = "Tool";
            // 
            // mJumpLastPath
            // 
            this.mJumpLastPath.Index = 0;
            this.mJumpLastPath.Text = "Path Backward\tLeft Arrow";
            this.mJumpLastPath.Click += new System.EventHandler(this.mJumpLastPath_Click);
            // 
            // mJumpNextPath
            // 
            this.mJumpNextPath.Index = 1;
            this.mJumpNextPath.Text = "Path Forward\tRight Arrow";
            this.mJumpNextPath.Click += new System.EventHandler(this.mJumpNextPath_Click);
            // 
            // menuItem18
            // 
            this.menuItem18.Index = 2;
            this.menuItem18.Text = "-";
            // 
            // mSeriesForward
            // 
            this.mSeriesForward.Index = 3;
            this.mSeriesForward.Text = "Prevoius Object\tUpArrow";
            this.mSeriesForward.Click += new System.EventHandler(this.mSeriesForward_Click);
            // 
            // mSeriesBackward
            // 
            this.mSeriesBackward.Index = 4;
            this.mSeriesBackward.Text = "Next Object\tDown Arrow";
            this.mSeriesBackward.Click += new System.EventHandler(this.mSeriesBackward_Click);
            // 
            // menuItem2
            // 
            this.menuItem2.Index = 5;
            this.menuItem2.Text = "-";
            // 
            // mCategorize
            // 
            this.mCategorize.Index = 6;
            this.mCategorize.Text = "Categorize Parsed Objects...";
            this.mCategorize.Click += new System.EventHandler(this.mCategorize_Click);
            // 
            // mCategorizeContours
            // 
            this.mCategorizeContours.Index = 7;
            this.mCategorizeContours.Text = "Categorize Contours...";
            this.mCategorizeContours.Click += new System.EventHandler(this.mCategorizeContours_Click);
            // 
            // menuItem13
            // 
            this.menuItem13.Index = 8;
            this.menuItem13.Text = "-";
            // 
            // mResetPixels
            // 
            this.mResetPixels.Index = 9;
            this.mResetPixels.Text = "Reset Pixels";
            this.mResetPixels.Click += new System.EventHandler(this.mResetPixels_Click);
            // 
            // mFindBadVert
            // 
            this.mFindBadVert.Index = 10;
            this.mFindBadVert.Text = "Find Unstandardized Polygons...";
            this.mFindBadVert.Click += new System.EventHandler(this.mFindBadVert_Click);
            // 
            // mElimRedundant
            // 
            this.mElimRedundant.Index = 11;
            this.mElimRedundant.Text = "Eliminate Redundant Vertices";
            this.mElimRedundant.Click += new System.EventHandler(this.mElimRedundant_Click);
            // 
            // mElimEmpty
            // 
            this.mElimEmpty.Index = 12;
            this.mElimEmpty.Text = "Eliminate Empty Objects and Polygons";
            this.mElimEmpty.Click += new System.EventHandler(this.mElimEmpty_Click);
            // 
            // mTidyOwnedEdges
            // 
            this.mTidyOwnedEdges.Index = 13;
            this.mTidyOwnedEdges.Text = "Tidy Owned Edges";
            this.mTidyOwnedEdges.Click += new System.EventHandler(this.mTidyOwnedEdges_Click);
            // 
            // mUnswallowAll
            // 
            this.mUnswallowAll.Index = 14;
            this.mUnswallowAll.Text = "Unswallow All";
            this.mUnswallowAll.Click += new System.EventHandler(this.mUnswallowAll_Click);
            // 
            // menuItem5
            // 
            this.menuItem5.Index = 15;
            this.menuItem5.Text = "-";
            // 
            // mLogGabor
            // 
            this.mLogGabor.Index = 16;
            this.mLogGabor.Text = "Log Gabor Filtering...";
            this.mLogGabor.Click += new System.EventHandler(this.mLogGabor_Click);
            // 
            // mOptions
            // 
            this.mOptions.Index = 5;
            this.mOptions.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mOptionsColors,
            this.mOptionsAlphas,
            this.menuItem3});
            this.mOptions.Text = "Options";
            // 
            // mOptionsColors
            // 
            this.mOptionsColors.Index = 0;
            this.mOptionsColors.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mOpsColsPolyLine,
            this.mOpsColsCurObj,
            this.mOpsColsOtherObj,
            this.mOpsColsNonObj});
            this.mOptionsColors.Text = "Colors";
            // 
            // mOpsColsPolyLine
            // 
            this.mOpsColsPolyLine.Index = 0;
            this.mOpsColsPolyLine.Text = "Polygon Line";
            this.mOpsColsPolyLine.Click += new System.EventHandler(this.mOpsColsPolyLine_Click);
            // 
            // mOpsColsCurObj
            // 
            this.mOpsColsCurObj.Index = 1;
            this.mOpsColsCurObj.Text = "Current Object";
            this.mOpsColsCurObj.Click += new System.EventHandler(this.mOpsColsCurObj_Click);
            // 
            // mOpsColsOtherObj
            // 
            this.mOpsColsOtherObj.Index = 2;
            this.mOpsColsOtherObj.Text = "Within-Category Objects";
            this.mOpsColsOtherObj.Click += new System.EventHandler(this.mOpsColsOtherObj_Click);
            // 
            // mOpsColsNonObj
            // 
            this.mOpsColsNonObj.Index = 3;
            this.mOpsColsNonObj.Text = "Non-Category Objects Within Pixel Exclusive Scope";
            this.mOpsColsNonObj.Click += new System.EventHandler(this.mOpsColsNonObj_Click);
            // 
            // mOptionsAlphas
            // 
            this.mOptionsAlphas.Index = 1;
            this.mOptionsAlphas.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mOpsAlphaPolyLine,
            this.mOpsAlphaCurObj,
            this.mOpsAlphaOtherObj,
            this.mOpsAlphaNonObj});
            this.mOptionsAlphas.Text = "Alphas";
            // 
            // mOpsAlphaPolyLine
            // 
            this.mOpsAlphaPolyLine.Index = 0;
            this.mOpsAlphaPolyLine.Text = "Polygon Line";
            this.mOpsAlphaPolyLine.Click += new System.EventHandler(this.mOpsAlphaPolyLine_Click);
            // 
            // mOpsAlphaCurObj
            // 
            this.mOpsAlphaCurObj.Index = 1;
            this.mOpsAlphaCurObj.Text = "Current Object";
            this.mOpsAlphaCurObj.Click += new System.EventHandler(this.mOpsAlphaCurObj_Click);
            // 
            // mOpsAlphaOtherObj
            // 
            this.mOpsAlphaOtherObj.Index = 2;
            this.mOpsAlphaOtherObj.Text = "Within-Category Objects";
            this.mOpsAlphaOtherObj.Click += new System.EventHandler(this.mOpsAlphaOtherObj_Click);
            // 
            // mOpsAlphaNonObj
            // 
            this.mOpsAlphaNonObj.Index = 3;
            this.mOpsAlphaNonObj.Text = "Non-Category Objects Within Pixel Exclusive Scope";
            this.mOpsAlphaNonObj.Click += new System.EventHandler(this.mOpsAlphaNonObj_Click);
            // 
            // menuItem3
            // 
            this.menuItem3.Index = 2;
            this.menuItem3.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mNearNeighbor,
            this.mBilinear});
            this.menuItem3.Text = "Interpolation";
            // 
            // mNearNeighbor
            // 
            this.mNearNeighbor.Index = 0;
            this.mNearNeighbor.RadioCheck = true;
            this.mNearNeighbor.Text = "Nearest Neighbor";
            this.mNearNeighbor.Click += new System.EventHandler(this.mNearNeighbor_Click);
            // 
            // mBilinear
            // 
            this.mBilinear.Checked = true;
            this.mBilinear.Index = 1;
            this.mBilinear.RadioCheck = true;
            this.mBilinear.Text = "Bilinear";
            this.mBilinear.Click += new System.EventHandler(this.mBilinear_Click);
            // 
            // mHelp
            // 
            this.mHelp.Index = 6;
            this.mHelp.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mTutorial,
            this.mHelpKeyMouse,
            this.mAbout});
            this.mHelp.Text = "Help";
            // 
            // mTutorial
            // 
            this.mTutorial.Index = 0;
            this.mTutorial.Text = "Tutorial";
            this.mTutorial.Click += new System.EventHandler(this.mTutorial_Click);
            // 
            // mHelpKeyMouse
            // 
            this.mHelpKeyMouse.Index = 1;
            this.mHelpKeyMouse.Text = "Keyboard-Mouse Functionality";
            this.mHelpKeyMouse.Click += new System.EventHandler(this.mHelpKeyMouse_Click);
            // 
            // mAbout
            // 
            this.mAbout.Index = 2;
            this.mAbout.Text = "Usage Rights";
            this.mAbout.Click += new System.EventHandler(this.mAbout_Click);
            // 
            // sfdOutput
            // 
            this.sfdOutput.Filter = "Text File | *.txt";
            // 
            // Tv
            // 
            this.Tv.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                        | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.Tv.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.Tv.ContextMenu = this.contextMenu1;
            this.Tv.LabelEdit = true;
            this.Tv.Location = new System.Drawing.Point(0, 0);
            this.Tv.Name = "Tv";
            this.Tv.ShowNodeToolTips = true;
            this.Tv.Size = new System.Drawing.Size(192, 253);
            this.Tv.TabIndex = 3;
            this.Tv.NodeMouseDoubleClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.Tv_NodeMouseDoubleClick);
            this.Tv.MouseEnter += new System.EventHandler(this.Tv_MouseEnter);
            this.Tv.NodeMouseHover += new System.Windows.Forms.TreeNodeMouseHoverEventHandler(this.Tv_NodeMouseHover);
            this.Tv.AfterLabelEdit += new System.Windows.Forms.NodeLabelEditEventHandler(this.Tv_AfterLabelEdit);
            this.Tv.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.Tv_AfterSelect);
            this.Tv.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Tv_MouseDown);
            // 
            // contextMenu1
            // 
            this.contextMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mNewPixScope,
            this.mNewSubCat,
            this.mNewSubObj,
            this.mNewSubPoly,
            this.mNewSubContour,
            this.mNewCircle,
            this.menuItem19,
            this.mColor,
            this.mColorRevert,
            this.menuItem4,
            this.mCut,
            this.mPaste,
            this.mDelete,
            this.menuItem20,
            this.cmViewEdgePoints});
            this.contextMenu1.Popup += new System.EventHandler(this.contextMenu1_Popup);
            // 
            // mNewPixScope
            // 
            this.mNewPixScope.Index = 0;
            this.mNewPixScope.Text = "New Pixel Scope";
            this.mNewPixScope.Click += new System.EventHandler(this.mNewSubCat_Click);
            // 
            // mNewSubCat
            // 
            this.mNewSubCat.Index = 1;
            this.mNewSubCat.Text = "New Subordinate Category Node";
            this.mNewSubCat.Click += new System.EventHandler(this.mNewSubCat_Click);
            // 
            // mNewSubObj
            // 
            this.mNewSubObj.Index = 2;
            this.mNewSubObj.Text = "New Subordinate Object";
            this.mNewSubObj.Click += new System.EventHandler(this.mNewSubObj_Click);
            // 
            // mNewSubPoly
            // 
            this.mNewSubPoly.Index = 3;
            this.mNewSubPoly.Text = "New Subordinate Polygon";
            this.mNewSubPoly.Click += new System.EventHandler(this.mNewSubPoly_Click);
            // 
            // mNewSubContour
            // 
            this.mNewSubContour.Index = 4;
            this.mNewSubContour.Text = "New Subordinate Contour";
            this.mNewSubContour.Click += new System.EventHandler(this.mNewSubContour_Click);
            // 
            // mNewCircle
            // 
            this.mNewCircle.Index = 5;
            this.mNewCircle.Text = "New Region of Interest (Circle)";
            this.mNewCircle.Click += new System.EventHandler(this.mNewCircle_Click);
            // 
            // menuItem19
            // 
            this.menuItem19.Index = 6;
            this.menuItem19.Text = "-";
            // 
            // mColor
            // 
            this.mColor.Index = 7;
            this.mColor.Text = "Color...";
            this.mColor.Click += new System.EventHandler(this.mColor_Click);
            // 
            // mColorRevert
            // 
            this.mColorRevert.Index = 8;
            this.mColorRevert.Text = "Revert to Default Color";
            this.mColorRevert.Click += new System.EventHandler(this.mColorRevert_Click);
            // 
            // menuItem4
            // 
            this.menuItem4.Index = 9;
            this.menuItem4.Text = "-";
            // 
            // mCut
            // 
            this.mCut.Index = 10;
            this.mCut.Shortcut = System.Windows.Forms.Shortcut.CtrlX;
            this.mCut.Text = "Cut";
            this.mCut.Click += new System.EventHandler(this.mCut_Click);
            // 
            // mPaste
            // 
            this.mPaste.Index = 11;
            this.mPaste.Shortcut = System.Windows.Forms.Shortcut.CtrlV;
            this.mPaste.Text = "Paste";
            this.mPaste.Click += new System.EventHandler(this.mPaste_Click);
            // 
            // mDelete
            // 
            this.mDelete.Index = 12;
            this.mDelete.Text = "Delete";
            this.mDelete.Click += new System.EventHandler(this.mDelete_Click);
            // 
            // menuItem20
            // 
            this.menuItem20.Index = 13;
            this.menuItem20.Text = "-";
            // 
            // cmViewEdgePoints
            // 
            this.cmViewEdgePoints.Index = 14;
            this.cmViewEdgePoints.Text = "View Edge Points (dpix=1)";
            this.cmViewEdgePoints.Click += new System.EventHandler(this.cmViewEdgePoints_Click);
            // 
            // panelMain
            // 
            this.panelMain.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                        | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.panelMain.Controls.Add(this.panelRight);
            this.panelMain.Controls.Add(this.splitMainVert);
            this.panelMain.Controls.Add(this.panelLeft);
            this.panelMain.Location = new System.Drawing.Point(0, 24);
            this.panelMain.Name = "panelMain";
            this.panelMain.Size = new System.Drawing.Size(587, 253);
            this.panelMain.TabIndex = 6;
            // 
            // panelRight
            // 
            this.panelRight.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                        | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.panelRight.Controls.Add(this.splitRightHor);
            this.panelRight.Controls.Add(this.PbRibbon);
            this.panelRight.Controls.Add(this.Pb);
            this.panelRight.ImeMode = System.Windows.Forms.ImeMode.Off;
            this.panelRight.Location = new System.Drawing.Point(195, 0);
            this.panelRight.Name = "panelRight";
            this.panelRight.Size = new System.Drawing.Size(392, 253);
            this.panelRight.TabIndex = 9;
            this.panelRight.SizeChanged += new System.EventHandler(this.panelRight_SizeChanged);
            // 
            // splitRightHor
            // 
            this.splitRightHor.BackColor = System.Drawing.SystemColors.InactiveCaption;
            this.splitRightHor.Dock = System.Windows.Forms.DockStyle.Bottom;
            this.splitRightHor.Location = new System.Drawing.Point(0, 122);
            this.splitRightHor.Name = "splitRightHor";
            this.splitRightHor.Size = new System.Drawing.Size(392, 3);
            this.splitRightHor.TabIndex = 8;
            this.splitRightHor.TabStop = false;
            this.splitRightHor.DoubleClick += new System.EventHandler(this.splitRightHor_DoubleClick);
            this.splitRightHor.SplitterMoved += new System.Windows.Forms.SplitterEventHandler(this.splitRightHor_SplitterMoved);
            // 
            // PbRibbon
            // 
            this.PbRibbon.BackColor = System.Drawing.SystemColors.ControlLight;
            this.PbRibbon.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.PbRibbon.Cursor = System.Windows.Forms.Cursors.Cross;
            this.PbRibbon.Dock = System.Windows.Forms.DockStyle.Bottom;
            this.PbRibbon.Location = new System.Drawing.Point(0, 125);
            this.PbRibbon.Name = "PbRibbon";
            this.PbRibbon.Size = new System.Drawing.Size(392, 128);
            this.PbRibbon.TabIndex = 7;
            this.PbRibbon.TabStop = false;
            this.PbRibbon.MouseLeave += new System.EventHandler(this.PbRibbon_MouseLeave);
            this.PbRibbon.MouseDown += new System.Windows.Forms.MouseEventHandler(this.PbRibbon_MouseDown);
            this.PbRibbon.MouseMove += new System.Windows.Forms.MouseEventHandler(this.PbRibbon_MouseMove);
            this.PbRibbon.Paint += new System.Windows.Forms.PaintEventHandler(this.PbRibbon_Paint);
            this.PbRibbon.MouseEnter += new System.EventHandler(this.PbRibbon_MouseEnter);
            // 
            // Pb
            // 
            this.Pb.BackColor = System.Drawing.SystemColors.ControlDark;
            this.Pb.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.Pb.Cursor = System.Windows.Forms.Cursors.Cross;
            this.Pb.Location = new System.Drawing.Point(0, 0);
            this.Pb.Name = "Pb";
            this.Pb.Size = new System.Drawing.Size(485, 352);
            this.Pb.TabIndex = 5;
            this.Pb.TabStop = false;
            this.Pb.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Pb_MouseDown);
            this.Pb.MouseMove += new System.Windows.Forms.MouseEventHandler(this.Pb_MouseMove);
            this.Pb.Paint += new System.Windows.Forms.PaintEventHandler(this.Pb_Paint);
            this.Pb.MouseUp += new System.Windows.Forms.MouseEventHandler(this.Pb_MouseUp);
            this.Pb.MouseEnter += new System.EventHandler(this.Pb_MouseEnter);
            this.Pb.SizeChanged += new System.EventHandler(this.Pb_SizeChanged);
            // 
            // splitMainVert
            // 
            this.splitMainVert.BackColor = System.Drawing.SystemColors.InactiveCaption;
            this.splitMainVert.Location = new System.Drawing.Point(192, 0);
            this.splitMainVert.Name = "splitMainVert";
            this.splitMainVert.Size = new System.Drawing.Size(3, 253);
            this.splitMainVert.TabIndex = 8;
            this.splitMainVert.TabStop = false;
            this.splitMainVert.SplitterMoved += new System.Windows.Forms.SplitterEventHandler(this.splitMainVert_SplitterMoved);
            this.splitMainVert.SplitterMoving += new System.Windows.Forms.SplitterEventHandler(this.splitMainVert_SplitterMoving);
            // 
            // panelLeft
            // 
            this.panelLeft.Controls.Add(this.Tv);
            this.panelLeft.Dock = System.Windows.Forms.DockStyle.Left;
            this.panelLeft.Location = new System.Drawing.Point(0, 0);
            this.panelLeft.Name = "panelLeft";
            this.panelLeft.Size = new System.Drawing.Size(192, 253);
            this.panelLeft.TabIndex = 7;
            // 
            // toolTip1
            // 
            this.toolTip1.AutoPopDelay = 0;
            this.toolTip1.InitialDelay = 500;
            this.toolTip1.ReshowDelay = 100;
            // 
            // bViewAll
            // 
            this.bViewAll.ImageIndex = 1;
            this.bViewAll.ImageList = this.imViewAll;
            this.bViewAll.Location = new System.Drawing.Point(58, 0);
            this.bViewAll.Name = "bViewAll";
            this.bViewAll.Size = new System.Drawing.Size(24, 24);
            this.bViewAll.TabIndex = 9;
            this.bViewAll.Tag = "";
            this.toolTip1.SetToolTip(this.bViewAll, "View Image Only (Toggle with Spacebar)");
            this.bViewAll.Paint += new System.Windows.Forms.PaintEventHandler(this.bViewButton_Paint);
            this.bViewAll.MouseUp += new System.Windows.Forms.MouseEventHandler(this.bViewButton_MouseUp);
            // 
            // imViewAll
            // 
            this.imViewAll.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imViewAll.ImageStream")));
            this.imViewAll.TransparentColor = System.Drawing.Color.Transparent;
            this.imViewAll.Images.SetKeyName(0, "bViewAll_unselected.jpg");
            this.imViewAll.Images.SetKeyName(1, "bViewAll_selected.jpg");
            // 
            // bViewInactiveCat
            // 
            this.bViewInactiveCat.ImageIndex = 1;
            this.bViewInactiveCat.ImageList = this.imViewInactiveCat;
            this.bViewInactiveCat.Location = new System.Drawing.Point(84, 0);
            this.bViewInactiveCat.Name = "bViewInactiveCat";
            this.bViewInactiveCat.Size = new System.Drawing.Size(24, 24);
            this.bViewInactiveCat.TabIndex = 10;
            this.bViewInactiveCat.Tag = "";
            this.toolTip1.SetToolTip(this.bViewInactiveCat, "View Inactive Categories (Toggle)");
            this.bViewInactiveCat.Paint += new System.Windows.Forms.PaintEventHandler(this.bViewButton_Paint);
            this.bViewInactiveCat.MouseUp += new System.Windows.Forms.MouseEventHandler(this.bViewButton_MouseUp);
            // 
            // imViewInactiveCat
            // 
            this.imViewInactiveCat.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imViewInactiveCat.ImageStream")));
            this.imViewInactiveCat.TransparentColor = System.Drawing.Color.Transparent;
            this.imViewInactiveCat.Images.SetKeyName(0, "bViewInactiveCat_unselected.jpg");
            this.imViewInactiveCat.Images.SetKeyName(1, "bViewInactiveCat_selected.jpg");
            // 
            // bViewActiveCat
            // 
            this.bViewActiveCat.ImageIndex = 2;
            this.bViewActiveCat.ImageList = this.imViewActiveCat;
            this.bViewActiveCat.Location = new System.Drawing.Point(108, 0);
            this.bViewActiveCat.Name = "bViewActiveCat";
            this.bViewActiveCat.Size = new System.Drawing.Size(24, 24);
            this.bViewActiveCat.TabIndex = 11;
            this.bViewActiveCat.Tag = "";
            this.toolTip1.SetToolTip(this.bViewActiveCat, "View Active Category (4-way Toggle)");
            this.bViewActiveCat.Paint += new System.Windows.Forms.PaintEventHandler(this.bViewButton_Paint);
            this.bViewActiveCat.MouseUp += new System.Windows.Forms.MouseEventHandler(this.bViewButton_MouseUp);
            // 
            // imViewActiveCat
            // 
            this.imViewActiveCat.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imViewActiveCat.ImageStream")));
            this.imViewActiveCat.TransparentColor = System.Drawing.Color.Transparent;
            this.imViewActiveCat.Images.SetKeyName(0, "bViewActiveCat_0_2.jpg");
            this.imViewActiveCat.Images.SetKeyName(1, "bViewActiveCat_1_2.jpg");
            this.imViewActiveCat.Images.SetKeyName(2, "bViewActiveCat_2_2.jpg");
            // 
            // bViewEdges
            // 
            this.bViewEdges.ImageIndex = 1;
            this.bViewEdges.ImageList = this.imViewEdge;
            this.bViewEdges.Location = new System.Drawing.Point(134, 0);
            this.bViewEdges.Name = "bViewEdges";
            this.bViewEdges.Size = new System.Drawing.Size(24, 24);
            this.bViewEdges.TabIndex = 12;
            this.bViewEdges.Tag = "";
            this.toolTip1.SetToolTip(this.bViewEdges, "View Edges (3-way Toggle)");
            this.bViewEdges.Paint += new System.Windows.Forms.PaintEventHandler(this.bViewButton_Paint);
            this.bViewEdges.MouseUp += new System.Windows.Forms.MouseEventHandler(this.bViewButton_MouseUp);
            // 
            // imViewEdge
            // 
            this.imViewEdge.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imViewEdge.ImageStream")));
            this.imViewEdge.TransparentColor = System.Drawing.Color.Transparent;
            this.imViewEdge.Images.SetKeyName(0, "bViewEdge_0_2.jpg");
            this.imViewEdge.Images.SetKeyName(1, "bViewEdge_1_2.jpg");
            this.imViewEdge.Images.SetKeyName(2, "bViewEdge_2_2.jpg");
            // 
            // bViewPoly
            // 
            this.bViewPoly.ImageIndex = 1;
            this.bViewPoly.ImageList = this.imViewPoly;
            this.bViewPoly.Location = new System.Drawing.Point(160, 0);
            this.bViewPoly.Name = "bViewPoly";
            this.bViewPoly.Size = new System.Drawing.Size(24, 24);
            this.bViewPoly.TabIndex = 14;
            this.bViewPoly.Tag = "";
            this.toolTip1.SetToolTip(this.bViewPoly, "View Polygon (3-way Toggle)");
            this.bViewPoly.Paint += new System.Windows.Forms.PaintEventHandler(this.bViewButton_Paint);
            this.bViewPoly.MouseUp += new System.Windows.Forms.MouseEventHandler(this.bViewButton_MouseUp);
            // 
            // imViewPoly
            // 
            this.imViewPoly.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imViewPoly.ImageStream")));
            this.imViewPoly.TransparentColor = System.Drawing.Color.Transparent;
            this.imViewPoly.Images.SetKeyName(0, "bViewPoly_0_2.jpg");
            this.imViewPoly.Images.SetKeyName(1, "bViewPoly_1_2.jpg");
            this.imViewPoly.Images.SetKeyName(2, "bViewPoly_2_2.jpg");
            // 
            // bViewActiveCircle
            // 
            this.bViewActiveCircle.ImageIndex = 1;
            this.bViewActiveCircle.ImageList = this.imViewCircle;
            this.bViewActiveCircle.Location = new System.Drawing.Point(286, 0);
            this.bViewActiveCircle.Name = "bViewActiveCircle";
            this.bViewActiveCircle.Size = new System.Drawing.Size(24, 24);
            this.bViewActiveCircle.TabIndex = 10;
            this.bViewActiveCircle.Tag = "";
            this.toolTip1.SetToolTip(this.bViewActiveCircle, "View Active Circle (Toggle)");
            this.bViewActiveCircle.Paint += new System.Windows.Forms.PaintEventHandler(this.bViewButton_Paint);
            this.bViewActiveCircle.MouseUp += new System.Windows.Forms.MouseEventHandler(this.bViewButton_MouseUp);
            // 
            // imViewCircle
            // 
            this.imViewCircle.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imViewCircle.ImageStream")));
            this.imViewCircle.TransparentColor = System.Drawing.Color.Transparent;
            this.imViewCircle.Images.SetKeyName(0, "bViewCircle_unselected.jpg");
            this.imViewCircle.Images.SetKeyName(1, "bViewCircle_selected.jpg");
            // 
            // bLinkMode
            // 
            this.bLinkMode.ImageIndex = 0;
            this.bLinkMode.ImageList = this.imLinkMode;
            this.bLinkMode.Location = new System.Drawing.Point(320, 0);
            this.bLinkMode.Name = "bLinkMode";
            this.bLinkMode.Size = new System.Drawing.Size(24, 24);
            this.bLinkMode.TabIndex = 11;
            this.bLinkMode.Tag = "";
            this.toolTip1.SetToolTip(this.bLinkMode, "Link Mode (Toggle)");
            this.bLinkMode.Click += new System.EventHandler(this.bLinkMode_Click);
            this.bLinkMode.Paint += new System.Windows.Forms.PaintEventHandler(this.bLinkMode_Paint);
            // 
            // imLinkMode
            // 
            this.imLinkMode.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imLinkMode.ImageStream")));
            this.imLinkMode.TransparentColor = System.Drawing.Color.Transparent;
            this.imLinkMode.Images.SetKeyName(0, "bModeLink_unselected.jpg");
            this.imLinkMode.Images.SetKeyName(1, "bModeLink_selected.jpg");
            // 
            // bViewContours
            // 
            this.bViewContours.ImageIndex = 1;
            this.bViewContours.ImageList = this.imViewContour;
            this.bViewContours.Location = new System.Drawing.Point(184, 0);
            this.bViewContours.Name = "bViewContours";
            this.bViewContours.Size = new System.Drawing.Size(24, 24);
            this.bViewContours.TabIndex = 15;
            this.bViewContours.Tag = "";
            this.toolTip1.SetToolTip(this.bViewContours, "View Contours (3-way Toggle)");
            this.bViewContours.Paint += new System.Windows.Forms.PaintEventHandler(this.bViewButton_Paint);
            this.bViewContours.MouseUp += new System.Windows.Forms.MouseEventHandler(this.bViewButton_MouseUp);
            // 
            // imViewContour
            // 
            this.imViewContour.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imViewContour.ImageStream")));
            this.imViewContour.TransparentColor = System.Drawing.Color.Transparent;
            this.imViewContour.Images.SetKeyName(0, "bViewContour_0_2.jpg");
            this.imViewContour.Images.SetKeyName(1, "bViewContour_1_2.jpg");
            this.imViewContour.Images.SetKeyName(2, "bViewContour_2_2.jpg");
            // 
            // bViewXjunc
            // 
            this.bViewXjunc.ImageIndex = 0;
            this.bViewXjunc.ImageList = this.imViewXjunc;
            this.bViewXjunc.Location = new System.Drawing.Point(210, 0);
            this.bViewXjunc.Name = "bViewXjunc";
            this.bViewXjunc.Size = new System.Drawing.Size(24, 24);
            this.bViewXjunc.TabIndex = 11;
            this.bViewXjunc.Tag = "";
            this.toolTip1.SetToolTip(this.bViewXjunc, "View X-junctions (3-way Toggle)");
            this.bViewXjunc.Paint += new System.Windows.Forms.PaintEventHandler(this.bViewButton_Paint);
            this.bViewXjunc.MouseUp += new System.Windows.Forms.MouseEventHandler(this.bViewButton_MouseUp);
            // 
            // imViewXjunc
            // 
            this.imViewXjunc.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imViewXjunc.ImageStream")));
            this.imViewXjunc.TransparentColor = System.Drawing.Color.Transparent;
            this.imViewXjunc.Images.SetKeyName(0, "bViewXjunc_0_2.jpg");
            this.imViewXjunc.Images.SetKeyName(1, "bViewXjunc_1_2.jpg");
            this.imViewXjunc.Images.SetKeyName(2, "bViewXjunc_2_2.jpg");
            // 
            // bViewTjunc
            // 
            this.bViewTjunc.ImageIndex = 0;
            this.bViewTjunc.ImageList = this.imViewTjunc;
            this.bViewTjunc.Location = new System.Drawing.Point(234, 0);
            this.bViewTjunc.Name = "bViewTjunc";
            this.bViewTjunc.Size = new System.Drawing.Size(24, 24);
            this.bViewTjunc.TabIndex = 12;
            this.bViewTjunc.Tag = "";
            this.toolTip1.SetToolTip(this.bViewTjunc, "View T-junctions (3-way Toggle)");
            this.bViewTjunc.Paint += new System.Windows.Forms.PaintEventHandler(this.bViewButton_Paint);
            this.bViewTjunc.MouseUp += new System.Windows.Forms.MouseEventHandler(this.bViewButton_MouseUp);
            // 
            // imViewTjunc
            // 
            this.imViewTjunc.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imViewTjunc.ImageStream")));
            this.imViewTjunc.TransparentColor = System.Drawing.Color.Transparent;
            this.imViewTjunc.Images.SetKeyName(0, "bViewTjunc_0_2.jpg");
            this.imViewTjunc.Images.SetKeyName(1, "bViewTjunc_1_2.jpg");
            this.imViewTjunc.Images.SetKeyName(2, "bViewTjunc_2_2.jpg");
            // 
            // bViewVertices
            // 
            this.bViewVertices.ImageIndex = 1;
            this.bViewVertices.ImageList = this.imViewVertices;
            this.bViewVertices.Location = new System.Drawing.Point(260, 0);
            this.bViewVertices.Name = "bViewVertices";
            this.bViewVertices.Size = new System.Drawing.Size(24, 24);
            this.bViewVertices.TabIndex = 16;
            this.bViewVertices.Tag = "";
            this.toolTip1.SetToolTip(this.bViewVertices, "View Active Vertices (Toggle)");
            this.bViewVertices.Paint += new System.Windows.Forms.PaintEventHandler(this.bViewButton_Paint);
            this.bViewVertices.MouseUp += new System.Windows.Forms.MouseEventHandler(this.bViewButton_MouseUp);
            // 
            // imViewVertices
            // 
            this.imViewVertices.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imViewVertices.ImageStream")));
            this.imViewVertices.TransparentColor = System.Drawing.Color.Transparent;
            this.imViewVertices.Images.SetKeyName(0, "bViewVertices_unselected.jpg");
            this.imViewVertices.Images.SetKeyName(1, "bViewVertices_selected.jpg");
            // 
            // pbTool
            // 
            this.pbTool.Location = new System.Drawing.Point(3, 0);
            this.pbTool.Name = "pbTool";
            this.pbTool.Size = new System.Drawing.Size(24, 24);
            this.pbTool.TabIndex = 17;
            this.pbTool.TabStop = false;
            this.toolTip1.SetToolTip(this.pbTool, "This icon displays which tool is active (if any):  Polygon, Contour, Region of In" +
                    "terest.");
            this.pbTool.Paint += new System.Windows.Forms.PaintEventHandler(this.pbTool_Paint);
            // 
            // imToolPoly
            // 
            this.imToolPoly.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imToolPoly.ImageStream")));
            this.imToolPoly.TransparentColor = System.Drawing.Color.Transparent;
            this.imToolPoly.Images.SetKeyName(0, "bToolPoly_unselected.jpg");
            this.imToolPoly.Images.SetKeyName(1, "bToolPoly_selected.jpg");
            // 
            // imToolContour
            // 
            this.imToolContour.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imToolContour.ImageStream")));
            this.imToolContour.TransparentColor = System.Drawing.Color.Transparent;
            this.imToolContour.Images.SetKeyName(0, "bToolContour_unselected.jpg");
            this.imToolContour.Images.SetKeyName(1, "bToolContour_selected.jpg");
            // 
            // panelFull
            // 
            this.panelFull.Controls.Add(this.pbTool);
            this.panelFull.Controls.Add(this.bViewVertices);
            this.panelFull.Controls.Add(this.bViewContours);
            this.panelFull.Controls.Add(this.bViewPoly);
            this.panelFull.Controls.Add(this.bViewEdges);
            this.panelFull.Controls.Add(this.bViewInactiveCat);
            this.panelFull.Controls.Add(this.panelBottom);
            this.panelFull.Controls.Add(this.panelMain);
            this.panelFull.Controls.Add(this.bViewAll);
            this.panelFull.Controls.Add(this.bViewActiveCat);
            this.panelFull.Controls.Add(this.bViewActiveCircle);
            this.panelFull.Controls.Add(this.bLinkMode);
            this.panelFull.Controls.Add(this.bViewXjunc);
            this.panelFull.Controls.Add(this.bViewTjunc);
            this.panelFull.Dock = System.Windows.Forms.DockStyle.Fill;
            this.panelFull.Location = new System.Drawing.Point(0, 0);
            this.panelFull.Name = "panelFull";
            this.panelFull.Size = new System.Drawing.Size(587, 302);
            this.panelFull.TabIndex = 7;
            // 
            // panelBottom
            // 
            this.panelBottom.Controls.Add(this.statusBar1);
            this.panelBottom.Dock = System.Windows.Forms.DockStyle.Bottom;
            this.panelBottom.Location = new System.Drawing.Point(0, 278);
            this.panelBottom.Name = "panelBottom";
            this.panelBottom.Size = new System.Drawing.Size(587, 24);
            this.panelBottom.TabIndex = 7;
            // 
            // statusBar1
            // 
            this.statusBar1.Location = new System.Drawing.Point(0, 0);
            this.statusBar1.Name = "statusBar1";
            this.statusBar1.Size = new System.Drawing.Size(587, 24);
            this.statusBar1.TabIndex = 0;
            this.statusBar1.Text = "Ready.";
            // 
            // OfdCameraSettings
            // 
            this.OfdCameraSettings.Multiselect = true;
            this.OfdCameraSettings.Title = "Select _t_f_s files with settings.";
            // 
            // OfdOpenBatch
            // 
            this.OfdOpenBatch.Filter = "Object Parser Files|*.ObjParser";
            this.OfdOpenBatch.Multiselect = true;
            this.OfdOpenBatch.Title = "Select files for batch process.";
            // 
            // imTool
            // 
            this.imTool.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imTool.ImageStream")));
            this.imTool.TransparentColor = System.Drawing.Color.Transparent;
            this.imTool.Images.SetKeyName(0, "bToolNone_selected.jpg");
            this.imTool.Images.SetKeyName(1, "bToolPoly_selected.jpg");
            this.imTool.Images.SetKeyName(2, "bToolContour_selected.jpg");
            this.imTool.Images.SetKeyName(3, "bToolCir_selected.jpg");
            // 
            // OfdBatchFix
            // 
            this.OfdBatchFix.FileName = "OfdBatchFix";
            // 
            // FormParse
            // 
            this.AllowDrop = true;
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.BackColor = System.Drawing.SystemColors.Control;
            this.ClientSize = new System.Drawing.Size(587, 302);
            this.Controls.Add(this.panelFull);
            this.ImeMode = System.Windows.Forms.ImeMode.Off;
            this.KeyPreview = true;
            this.Menu = this.menuProj;
            this.MinimumSize = new System.Drawing.Size(150, 150);
            this.Name = "FormParse";
            this.Text = "Object Parser";
            this.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.FormParse_MouseWheel);
            this.DragDrop += new System.Windows.Forms.DragEventHandler(this.FormParse_DragDrop);
            this.Resize += new System.EventHandler(this.FormParse_Resize);
            this.Closing += new System.ComponentModel.CancelEventHandler(this.FormParse_Closing);
            this.DragEnter += new System.Windows.Forms.DragEventHandler(this.FormParse_DragEnter);
            this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.FormParse_KeyUp);
            this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.FormParse_KeyDown);
            this.Load += new System.EventHandler(this.FormParse_Load);
            this.panelMain.ResumeLayout(false);
            this.panelRight.ResumeLayout(false);
            ((System.ComponentModel.ISupportInitialize)(this.PbRibbon)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.Pb)).EndInit();
            this.panelLeft.ResumeLayout(false);
            ((System.ComponentModel.ISupportInitialize)(this.pbTool)).EndInit();
            this.panelFull.ResumeLayout(false);
            this.panelBottom.ResumeLayout(false);
            this.ResumeLayout(false);

		}
		#endregion
		/// <summary>
		/// This is the ObjectParserData serializable instance information.
		/// </summary>
		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main(string[] args)
		{
			if(args.Length==0)
				Application.Run(new FormParse());
			else
				Application.Run( new FormParse(args[0]) );
		}
        FormRtb Rtb = null;
        public void OutputConsoleMessage(string text)
        {
            if(Rtb==null)
            {
                Rtb = new FormRtb(text);
                Rtb.Show();
            }
            else
                Rtb.Rtb.AppendText('\n'+text);
        }
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}
		public static Pen CirclePen, ClaimedPen, UnclaimedPen, SubPen, ClaimedPenDot, UnclaimedPenDot, SubPenDot;
		static FormParse()
		{
			CirclePen = new Pen( Color.FromArgb(255,125,20), 4.0f);
			CirclePen.DashOffset = 8.0f;
			CirclePen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;

			ClaimedPen = new Pen(Color.SkyBlue,1.0f);
			UnclaimedPen = new Pen(Color.Red,1.0f);
			SubPen = new Pen(Color.FromArgb(0,255,0),1.0f);

			ClaimedPenDot = new Pen(Color.SkyBlue,1.0f);
			ClaimedPenDot.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;

			UnclaimedPenDot = new Pen(Color.Red,1.0f);
			UnclaimedPenDot.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;

			SubPenDot = new Pen(Color.FromArgb(0,255,0),1.0f);
			SubPenDot.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;

			if(DbSources==null)
			{
				try
				{
					//	Try to deserialize a database.
					DbSources=DeserializeDbSources();
				}
				catch{}
				//	If the deserialization file does not exist, substitute the default DbSource object.
				if(DbSources==null)
					DbSources = new DbSource[] { new DbSource() };
			}
		}
		#region Tv Functionality
		/// <summary>
		/// Contents of the local clipboard that remembers which TreeNode was cut.
		/// </summary>
		public TreeNode TnClip;
		/// <summary>
		/// Initializes the images in the TreeNode
		/// </summary>
		public void InitTvImages()
		{
			ImageList il = new ImageList();

            il.Images.Add(Bitmap.FromFile(Application.StartupPath + "/Tv_Root.gif")); //0
            il.Images.Add(Bitmap.FromFile(Application.StartupPath + "/Tv_Cirs.gif")); //1
			il.Images.Add(Bitmap.FromFile(Application.StartupPath + "/TreeNodeImages_X.bmp")); //2
            il.Images.Add(Bitmap.FromFile(Application.StartupPath + "/TreeNodeImages_HX.bmp")); //3
			il.Images.Add(Bitmap.FromFile(Application.StartupPath + "/TreeNodeImages_O.bmp")); //4
            il.Images.Add(Bitmap.FromFile(Application.StartupPath + "/TreeNodeImages_HO.bmp")); //5			
            il.Images.Add(Bitmap.FromFile(Application.StartupPath + "/TreeNodeImages_Seg.bmp")); //6
            il.Images.Add(Bitmap.FromFile(Application.StartupPath + "/TreeNodeImages_HSeg.bmp")); //7			
			il.Images.Add(Bitmap.FromFile(Application.StartupPath + "/TreeNodeImages_Shadow.bmp")); //8
			il.Images.Add(Bitmap.FromFile(Application.StartupPath + "/TreeNodeImages_HShadow.bmp")); //9
            il.Images.Add(Bitmap.FromFile(Application.StartupPath + "/Tv_Poly_1.gif")); //10
            il.Images.Add(Bitmap.FromFile(Application.StartupPath + "/Tv_Poly_2.gif")); //11
            il.Images.Add(Bitmap.FromFile(Application.StartupPath + "/Tv_Con_1.gif")); //12
            il.Images.Add(Bitmap.FromFile(Application.StartupPath + "/Tv_Con_2.gif")); //13
            il.Images.Add(Bitmap.FromFile(Application.StartupPath + "/Tv_Cir_1.gif")); //14
            il.Images.Add(Bitmap.FromFile(Application.StartupPath + "/Tv_Cir_2.gif")); //15

			Tv.ImageList = il;
		}
        /// <summary>
        /// Gets the associated index into the TreeView's imagelist for the given object, which may or may not be active.
        /// </summary>
        /// <param name="o"></param>
        /// <param name="active"></param>
        /// <returns></returns>
        public static int ImageListIndex(object o,bool active)
        {
            int actInd = 0;
            if(active)
                actInd = 1;
            if(o.GetType()==typeof(CategoryNode))
            {
                if(((CategoryNode)o).Super==null)
                    return 0;
                else if(((CategoryNode)o).Super.Super==null)
                    return 2 + actInd;
                else
                    return 4 + actInd;
            }
            else if(o.GetType()==typeof(ParsedObject))
                return 6+actInd;
            else if(o.GetType()==typeof(PolygonF))
                return 10 + actInd;
            else if(o.GetType()==typeof(ContourF))
            {
                ContourF con = (ContourF)o;
                if(con.CatData!=null && con.CatData.ShadowBorder > 1)
                    return 8+actInd;
                else
                    return 12+actInd;
            }
            else if(o.GetType()==typeof(Circle[]))
                return 1;
            else if(o.GetType()==typeof(Circle))
            {
                if(((Circle)o).Display)
                    return 15;
                return 14;
            }
            return -1;
        }
        /// <summary>
        /// Returns the TreeNode object whose tag is equal to 'o'.
        /// </summary>
        /// <param name="o"></param>
        /// <returns></returns>
        public TreeNode NodeAttachedTo(object o)
        {
            return NodeAttachedTo(o,Tv.Nodes);
        }
        /// <summary>
        /// Returns the TreeNode object under 'tn' tag is equal to 'o'.
        /// </summary>
        /// <param name="o"></param>
        /// <param name="tn"></param>
        /// <returns></returns>
        public static TreeNode NodeAttachedTo(object o,TreeNodeCollection tnc)
        {
            int i;
            for(i=0;i<tnc.Count;i++)
            {
                if(tnc[i].Tag==o)
                    return tnc[i];
            }
            TreeNode result=null; ;
            for(i=0;i<tnc.Count;i++)
            {
                result = NodeAttachedTo(o,tnc[i].Nodes);
                if(result != null)
                    return result;
            }
            return result;
        }
        /// <summary>
        /// Is tree node "a" a descendant of tree node "b"?
        /// </summary>
        /// <param name="a">TreeNode a</param>
        /// <param name="b">TreeNode b</param>
        /// <returns>bool</returns>
        public static bool IsDescendantOf(TreeNode a,TreeNode b)
        {
            //	Is a descended from b?
            if(b==null) return false;
            if(a.Parent==b) return true;
            while(a.Parent != null)
            {
                a = a.Parent;
                if(a == b) return true;
            }
            return false;
        }
		/// <summary>
		/// Clears Tv and reconstructs it from member variables RootCategory.
		/// </summary>
		public void RefreshTv()
		{
			Tv.Nodes.Clear();

            TreeNode tn = new TreeNode("Regions Of Interest");
            if(Opd.Circles==null)
                Opd.Circles = new Circle[0];
            tn.Tag = Opd.Circles;
            tn.ImageIndex = ImageListIndex(Opd.Circles,false);
            tn.SelectedImageIndex = ImageListIndex(Opd.Circles,true);
            Tv.Nodes.Add(tn);

            TreeNode n;
            for(int i=0;i<Opd.Circles.Length;i++)
            {
                n = new TreeNode(Opd.Circles[i].Name);
                n.Tag = Opd.Circles[i];
                n.ImageIndex = ImageListIndex(Opd.Circles[i],false);
                n.SelectedImageIndex = ImageListIndex(Opd.Circles[i],true);
                tn.Nodes.Add(n);
            }

            //  Category Structure
			tn = new TreeNode(Opd.RootCategory.Name);
			tn.Tag = Opd.RootCategory;
            tn.ImageIndex = ImageListIndex(Opd.RootCategory,false);
            tn.SelectedImageIndex = ImageListIndex(Opd.RootCategory,true);
			Tv.Nodes.Add(tn);
			AddSubNodes(tn, Opd.RootCategory);
		}
        /// <summary>
        /// Useful when tn is already a representation of cn except the sub-nodes of tn need to be filled in.
        /// This adds the sub-nodes and objects of cn onto the nodes of tn.
        /// </summary>
        /// <param name="tn"></param>
        /// <param name="cn"></param>
        public static void AddSubNodes(TreeNode tn,CategoryNode cn)
		{
            int i,j,k;
            ParsedObject po;
            PolygonF poly;
            ContourF con;
            TreeNode n, nn, nnn;
			for(i=0; i<cn.Sub.Count; i++)
			{
				n = new TreeNode( ((CategoryNode)cn.Sub[i]).Name );
                n.ImageIndex = ImageListIndex(cn.Sub[i],false);
                n.SelectedImageIndex = ImageListIndex(cn.Sub[i],true);
				n.Tag = (CategoryNode)cn.Sub[i];
				AddSubNodes(n, (CategoryNode)cn.Sub[i]);
				tn.Nodes.Add(n);
			}
			for(i=0; i<cn.Objects.Count; i++)
			{
                po = cn.Objects[i];

				n = new TreeNode( po.Name );
				n.Tag = po;
				n.ImageIndex = ImageListIndex(po,false);
                n.SelectedImageIndex = ImageListIndex(po,true);
				tn.Nodes.Add(n);

                for(j=0;j<po.Polygons.Count;j++)
                {
                    poly = po.Polygons[j];
                    nn = new TreeNode(poly.Name);
                    nn.Tag = poly;
                    nn.ImageIndex = ImageListIndex(poly,false);
                    nn.SelectedImageIndex = ImageListIndex(poly,true);
                    if(poly.Color!=Color.Transparent)
                    {
                        nn.BackColor = poly.Color;
                        nn.ForeColor = NegativeColor(poly.Color);
                    }
                    n.Nodes.Add(nn);
                    for(k=0;k<poly.Contours.Count;k++)
                    {
                        con = poly.Contours[k];
                        nnn = new TreeNode(con.Name);
                        nnn.Tag = con;
                        nnn.ImageIndex = ImageListIndex(con,false);
                        nnn.SelectedImageIndex = ImageListIndex(con,true);
                        if(con.Color!=Color.Transparent)
                        {
                            nnn.BackColor = con.Color;
                            nnn.ForeColor = NegativeColor(con.Color);
                        }
                        nn.Nodes.Add(nnn);
                    }
                }
			}
		}
        /// <summary>
        /// When a tree-node is double-clicked, there is functionality depending on the tag of the TreeNode.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Tv_NodeMouseDoubleClick(object sender,TreeNodeMouseClickEventArgs e)
        {
            if(e.Node.Tag.GetType()==typeof(ParsedObject))
            {
                ParsedObject od = (ParsedObject)e.Node.Tag;
                ObjPropertiesDialog opd = new ObjPropertiesDialog(od);
                opd.ShowDialog();
            }
            else if(e.Node.Tag.GetType()==typeof(ContourF))
            {
                TreeNode tn = Tv.SelectedNode;
                ContourF con = (ContourF)tn.Tag;
                ConPropertiesDialog cpd = new ConPropertiesDialog(con);
                cpd.ShowDialog();
                tn.ImageIndex = ImageListIndex(con,false);
                tn.SelectedImageIndex = ImageListIndex(con,true);
                Tv.Invalidate();
            }
            else if(e.Node.Tag.GetType()==typeof(Circle))
            {
                ((Circle)e.Node.Tag).Display = !((Circle)e.Node.Tag).Display;
                e.Node.SelectedImageIndex = e.Node.ImageIndex = ImageListIndex(e.Node.Tag,true);
                Pb.Invalidate();
            }
            //  Note, it would be nice to have a contour categorization dialog open up.
        }
        /// <summary>
        /// Changes the name of a data element associated with a tree-node.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
		private void Tv_AfterLabelEdit(object sender, System.Windows.Forms.NodeLabelEditEventArgs e)
		{
			if(e.Node.Tag == typeof(ParsedObject))
			{
				if(e.Label != null)
					((ParsedObject)e.Node.Tag).Name = e.Label;
			}
            else if(Tv.SelectedNode.Tag.GetType() == typeof(CategoryNode))
			{
				CategoryNode cn = (CategoryNode)e.Node.Tag;
				if(!cn.IsRootCategory && e.Label != null)
					cn.Name = e.Label;
				else
					e.CancelEdit = true;
			}
            else if(Tv.SelectedNode.Tag.GetType() == typeof(PolygonF))
            {
                if(e.Label != null)
                    ((PolygonF)e.Node.Tag).Name = e.Label;
                else
                    e.CancelEdit = true;
            }
            else if(Tv.SelectedNode.Tag.GetType() == typeof(ContourF))
            {
                if(e.Label != null)
                    ((ContourF)e.Node.Tag).Name = e.Label;
                else
                    e.CancelEdit = true;
            }
            else if(Tv.SelectedNode.Tag.GetType() == typeof(Circle))
            {
                if(e.Label != null)
                    ((Circle)e.Node.Tag).Name = e.Label;
                else
                    e.CancelEdit = true;
            }
		}
		private void mNewSubCat_Click(object sender, System.EventArgs e)
		{
			TreeNode tn = Tv.SelectedNode;
			
            CategoryNode super = (CategoryNode)tn.Tag;
            string cname = "Category";
            if (super!=null && super.IsRootCategory)
                cname = "Scope";
			CategoryNode cn = new CategoryNode(cname, super, Opd);

            TreeNode node = new TreeNode(cn.Name);
            node.ImageIndex = ImageListIndex(cn,false);
            node.SelectedImageIndex = ImageListIndex(cn,true);
            node.Tag = cn;

            Cmd_AddNode cmd = new Cmd_AddNode(this,node,tn);

            //  If the command is valid
            if(cmd.Node!=null)
            {
                cmd.Redo();

                UndoStack.Add(cmd);
                RedoStack.Clear();
            }
		}
		public void mNewSubObj_Click(object sender, System.EventArgs e)
		{
            TreeNode tn = Tv.SelectedNode;

            CategoryNode super = (CategoryNode)tn.Tag;

            int i;

            TreeNode node = null;
            
            //  See if there is an empty object in there.
            ParsedObject po = null;
            for(i=0;po==null && i<super.Objects.Count;i++)
                if (super.Objects[i].Empty)
                {
                    po = super.Objects[i];
                    super.Objects.RemoveAt(i);
                    node = this.NodeAttachedTo(po);
                    if (node != null)
                        node.Remove();
                }

            //  No empty, make a new object
            if(po==null)
                po = new ParsedObject(Opd.ObjectCt++,super);

            node = new TreeNode(po.Name);
            node.Tag = po;
            node.ImageIndex = ImageListIndex(po,false);
            node.SelectedImageIndex = ImageListIndex(po,true);

            Cmd_AddNode cmd = new Cmd_AddNode(this,node, tn);

            //  If the command is valid
            if(cmd.Node!=null)
            {
                cmd.Redo();

                UndoStack.Add(cmd);
                RedoStack.Clear();
            }
		}
        private void mNewSubPoly_Click(object sender,EventArgs e)
        {
            TreeNode tn = Tv.SelectedNode;

            ParsedObject super = (ParsedObject)tn.Tag;
            PolygonF poly = new PolygonF(super);
            poly.Name = "polygon";
            TreeNode node = new TreeNode(poly.Name);
            node.ImageIndex = ImageListIndex(poly,false);
            node.SelectedImageIndex = ImageListIndex(poly,true);
            node.Tag = poly;

            Cmd_AddNode cmd = new Cmd_AddNode(this,node,tn);

            //  If the command is valid
            if(cmd.Node!=null)
            {
                cmd.Redo();

                UndoStack.Add(cmd);
                RedoStack.Clear();
            }
        }
        private void mNewSubContour_Click(object sender,EventArgs e)
        {
            TreeNode tn = Tv.SelectedNode;

            PolygonF super = (PolygonF)tn.Tag;
            ContourF con = new ContourF(super);
            con.Name = "contour";
            TreeNode node = new TreeNode(con.Name);
            node.ImageIndex = ImageListIndex(con,false);
            node.SelectedImageIndex = ImageListIndex(con,true);
            node.Tag = con;

            Cmd_AddNode cmd = new Cmd_AddNode(this,node,tn);

            //  If the command is valid
            if(cmd.Node!=null)
            {
                cmd.Redo();

                UndoStack.Add(cmd);
                RedoStack.Clear();
            }
        }
        private void mNewCircle_Click(object sender,EventArgs e)
        {
            TreeNode tn = Tv.SelectedNode;

            Circle cir = new Circle(new PointF(Opd.ImageWidth/2,Opd.ImageHeight/2),Math.Min(Opd.ImageWidth,Opd.ImageHeight)/4,true);
            cir.Name = "ROI";
            TreeNode node = new TreeNode(cir.Name);
            node.ImageIndex = ImageListIndex(cir,false);
            node.SelectedImageIndex = ImageListIndex(cir,true);
            node.Tag = cir;

            Cmd_AddNode cmd = new Cmd_AddNode(this,node,tn);

            //  If the command is valid
            if(cmd.Node!=null)
            {
                cmd.Redo();

                UndoStack.Add(cmd);
                RedoStack.Clear();
            }
        }
		private void mDelete_Click(object sender, System.EventArgs e)
		{
            TreeNode node = Tv.SelectedNode;
            TreeNode tn = node.Parent;

            if(tn!=null)    //cannot delete a top level node
            {
                Cmd_DeleteNode cmd = new Cmd_DeleteNode(this,node,tn);

                //  If the command is valid
                if(cmd.Node!=null)
                {
                    cmd.Redo();

                    UndoStack.Add(cmd);
                    RedoStack.Clear();
                }
            }
		}
		/// <summary>
		/// Suppresses switching to active category AND the Undo macro.
		/// </summary>
		public bool Tv_AfterSelect_SuppressSwitchActive = false;
		/// <summary>
		/// Suppresses the Undo macro.
		/// </summary>
		public bool Tv_AfterSelect_SuppressUndoMacro = false;
        /// <summary>
        /// The current selection in the TreeNode.
        /// </summary>
        public SelectionRecord CurrentSelection = null;
        /// <summary>
        /// The prevoius selection in the TreeNode.
        /// </summary>
        public SelectionRecord PreviousSelection = null;
		/// <summary>
		/// After a TreeNode in Tv is selected,  there is switching of the active thing and the associated
		/// macro.  This behavior can be suppressed by Tv_AfterSelect_SuppressSwitchActive and
		/// Tv_AfterSelect_SuppressUndoMacro.  The selected image index also changes (not suppressable).
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void Tv_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
		{
            if(e.Action==TreeViewAction.ByKeyboard || e.Action==TreeViewAction.ByMouse) // only respond to node selection changes.
            {
                if(!Tv_AfterSelect_SuppressSwitchActive && e.Node!=null)
                    ActivateSelection(e.Node.Tag,!this.Tv_AfterSelect_SuppressUndoMacro);
            }
		}
        /// <summary>
        /// Switches the currently active thing and handles all related functions such as
        /// updating the TreeView or adding an Undo command to the stack (if recordUndo==true)
        /// or updating the current tool.
        /// </summary>
        /// <param name="o"></param>
        /// <param name="recordUndo"></param>
        /// <returns></returns>
        public bool ActivateSelection(object o,bool recordUndo)
        {
            if(CurrentSelection.SelThing != o)
            {
                //  Record selection change and remember the last selection
                PreviousSelection = CurrentSelection;
                CurrentSelection = new SelectionRecord(o,this);
                if( o!=typeof(Circle) )
                    Opd.ActiveThing = o;
                SelectionRecord.UpdateBitmaps(PreviousSelection,CurrentSelection,this);

                //	Calculate edges.
                if(CurrentSelection.Poly!=null)
                    CurrentSelection.Poly.CalcEdges();

                //  Update Vertex Draw
                Ptool.UpdateVertexDraw();

                //  Redraw
                Pb.Invalidate();

                //  Update TreeView if necessary
                if(Tv.SelectedNode != CurrentSelection.SelNode)
                {
                    //	Suppress some Tv_AfterSelect functions.
                    bool lastSuppressVal = Tv_AfterSelect_SuppressSwitchActive;
                    Tv_AfterSelect_SuppressSwitchActive = true;
                    //	Select the new TreeNode
                    Tv.SelectedNode = CurrentSelection.SelNode;
                    //	Restore Tv_AfterSelect
                    Tv_AfterSelect_SuppressSwitchActive = lastSuppressVal;
                }

                //  Record Undo if requested
                if(recordUndo)
                {
                    UndoStack.Add(new Cmd_SwitchActive(this,PreviousSelection.SelThing,CurrentSelection.SelThing));
                    RedoStack.Clear();
                }

                //  Update the tool
                pbTool.Invalidate();
                if(CurrentSelection.SelThing==null)
                    CurrentTool = ToolType.None;
                else if(CurrentSelection.SelThing.GetType()==typeof(PolygonF))
                    CurrentTool = ToolType.Polygon;
                else if(CurrentSelection.SelThing.GetType()==typeof(ContourF))
                    CurrentTool = ToolType.Contour;
                else if(CurrentSelection.SelThing.GetType()==typeof(Circle))
                    CurrentTool = ToolType.Circle;
                else
                    CurrentTool = ToolType.None;

            }
            return true;

        }
        /// <summary>
        /// The current type of tool being used.
        /// </summary>
        public ToolType CurrentTool = ToolType.None;
		private void contextMenu1_Popup(object sender, System.EventArgs e)
		{
            int i;
            for(i=0;i<contextMenu1.MenuItems.Count;i++)
                contextMenu1.MenuItems[i].Enabled = ProjectLoaded;
            if(ProjectLoaded)
            {
                //  The selected node.
                TreeNode selected = Tv.SelectedNode;

                //	Do not allow deleting or moving the highest TreeNode objects.
                this.mDelete.Enabled = this.mCut.Enabled = selected.Parent!=null;

                //  Only add something appropriate to fall below the selected node.
                this.mNewPixScope.Enabled = (selected.Tag.GetType() == typeof(CategoryNode) && ((CategoryNode)selected.Tag).IsRootCategory);
                this.mNewSubCat.Enabled = (selected.Tag.GetType() == typeof(CategoryNode) && !((CategoryNode)selected.Tag).IsRootCategory);
                this.mNewSubObj.Enabled = selected.Parent!=null && selected.Tag.GetType()==typeof(CategoryNode);
                this.mNewSubPoly.Enabled = selected.Tag.GetType()==typeof(ParsedObject);
                this.mNewSubContour.Enabled = selected.Tag.GetType()==typeof(PolygonF);

                //  The circle node
                this.mNewCircle.Enabled = selected.Tag.GetType()==typeof(Circle[]);
                this.mCut.Enabled = !this.mNewCircle.Enabled;

                this.mColor.Enabled = selected.Tag.GetType()==typeof(PolygonF) || selected.Tag.GetType()==typeof(ContourF);
                this.mColorRevert.Enabled =
                        (selected.Tag.GetType()==typeof(PolygonF) || selected.Tag.GetType()==typeof(ContourF))
                    &&  ((PathF)selected.Tag).Color!=Color.Transparent;

                //	Do not allow pasting when the clipboard is empty.
                if(TnClip == null || selected.Parent==null || selected.Tag.GetType()==typeof(Circle))
                    this.mPaste.Enabled = false;
                else
                    this.mPaste.Enabled = selected!=TnClip && !IsDescendantOf(selected,TnClip);
            }
		}
		private void mCut_Click(object sender, System.EventArgs e)
		{
            TreeNode selected = Tv.SelectedNode;
			//	Set the clipboard
			if(selected.Parent != null && selected.Parent.Parent != null)	//	Not an in-exlcuded level and not a Circle, and not a highest TreeNode.
					TnClip = selected;
		}
		private void mPaste_Click(object sender, System.EventArgs e)
		{

            TreeNode tnPaste = Tv.SelectedNode;					//	The node being pasted into
            if(TnClip!=null && tnPaste!=null)
            {
                Cmd_MoveNode cmd = new Cmd_MoveNode(this,TnClip,TnClip.Parent,tnPaste);
                if(cmd.Node!= null) // if everything checked out as being valid
                {
                    cmd.Redo();
                    UndoStack.Add(cmd);
                    RedoStack.Clear();
                }
            }
            /*
            Tv.BeginUpdate();
			if(tnPaste.Tag.GetType()==TnClip.Parent.GetType())		//	Make sure you can paste into the correct thing.
				tnPaste = tnPaste.Parent;

			if(tnPaste!=TnClip && !IsDescendantOf(tnPaste, TnClip) && tnPaste.Parent!=null)
			{

				//	Clear the bitmaps
				ClearBitmaps(TnClip.Tag);

				CategoryNode parentCat = (CategoryNode)tnPaste.Tag;
				if(TnClip.Tag.GetType()==typeof(ParsedObject))		//	If the clipboard has an ParsedObject in it,
				{
					//	First, set the ObjectParserData info.

					//	Remove the object from the last active category's list of objects.
					((ParsedObject)TnClip.Tag).Category.Objects.Remove((ParsedObject)TnClip.Tag);

					//	Add the object to the new active category's list of objects.
					parentCat.Objects.Add((ParsedObject)TnClip.Tag);

					//	Set the ParsedObject's Category member to the appropriate parent category.
					((ParsedObject)TnClip.Tag).Category = parentCat;		
	
					//	Second, set the TreeNode display
					TnClip.Parent.Nodes.Remove(TnClip);
					tnPaste.Nodes.Add(TnClip);
				}
				else												//	The Clipboard has a CategoryNode in it.
				{
					//	First, set the ObjectParserData info.

					//	Remove the category from its old superordinate.
					((CategoryNode)TnClip.Tag).Super.Sub.Remove( (CategoryNode)TnClip.Tag );

					//	Add the object to its new superordinate.
					parentCat.Sub.Add((CategoryNode)TnClip.Tag);

					//	Set the ParsedObject's Category member to the appropriate parent category.
					((CategoryNode)TnClip.Tag).Super = parentCat;			

					//	Second, set the TreeNode display
					TnClip.Parent.Nodes.Remove(TnClip);
					tnPaste.Nodes.Insert(0,TnClip);
				}

				//	Clear the bitmaps
				PaintBitmaps(TnClip.Tag);
				Pb.Invalidate();
			}
			Tv.EndUpdate();
            */
		}
        private void mColor_Click(object sender,EventArgs e)
        {
            ColorDialog cd = new ColorDialog();
            cd.AllowFullOpen = true;
            cd.AnyColor=true;
            cd.SolidColorOnly = true;
            cd.Color = Opd.PolyLineColor;
            PathF path = (PathF)CurrentSelection.SelNode.Tag;
            if(path.Color!=Color.Transparent)
                cd.Color = path.Color;
            if(cd.ShowDialog() == DialogResult.OK)
            {
                path.Color = cd.Color;
                Pb.Invalidate();
                CurrentSelection.SelNode.BackColor = path.Color;
                CurrentSelection.SelNode.ForeColor = NegativeColor(path.Color);
            }
        }
        private void mColorRevert_Click(object sender,EventArgs e)
        {
            ((PathF)CurrentSelection.SelNode.Tag).Color = Color.Transparent;
            CurrentSelection.SelNode.BackColor = Tv.BackColor;
            CurrentSelection.SelNode.ForeColor = Tv.ForeColor;
            Pb.Invalidate();
        }
        private void Tv_NodeMouseHover(object sender,TreeNodeMouseHoverEventArgs e)
        {
            e.Node.ToolTipText = "";
            if(e.Node.Tag.GetType()==typeof(CategoryNode))
            {
                e.Node.ToolTipText = ((CategoryNode)e.Node.Tag).Tooltip;
            }
            else if(e.Node.Tag.GetType()==typeof(ParsedObject))
            {
                e.Node.ToolTipText = ((ParsedObject)e.Node.Tag).TooltipText;
            }
            else if(e.Node.Tag.GetType()==typeof(PolygonF))
            {
            }
            else if(e.Node.Tag.GetType()==typeof(ContourF))
            {
            }
            else if(e.Node.Tag.GetType()==typeof(Circle))
            {
                e.Node.ToolTipText = ((Circle)e.Node.Tag).ToString()+
                    "\nHold the Ctrl Key to change the radius with the mouse's wheel or move the circle with the mouse's R-button.\nDouble-click to toggle circle on or off.";
            }
        }
		private void Tv_MouseEnter(object sender, System.EventArgs e)
		{
			if(!this.Focused)
				this.Focus();
		}
		private void Tv_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			if(e.Button == MouseButtons.Right)
			{
				Point pt = Tv.PointToClient(Cursor.Position);
				TreeNode tn = Tv.GetNodeAt(pt);
				if(tn!=null)
					Tv.SelectedNode = tn;
			}
        }
        public static Color NegativeColor(Color pos)
        {
            int r,g,b;
            if(pos.R > 128)
                r = 0;
            else
                r = 255;
            if(pos.G > 128)
                g = 0;
            else
                g = 255;
            if(pos.B > 128)
                b = 0;
            else
                b = 255;
            return Color.FromArgb(r,g,b);
        }
        #endregion
        #region Undo, Redo, ExecuteAction, ModifiedTag
        /// <summary>
		/// List of commands in Undo.  CheckUndoStack() limits the size of the Undo stack.
		/// </summary>
		public ArrayList UndoStack;
		/// <summary>
		/// Limits the Undo stack to a size of 20 (thus preventing over-use of memory).
		/// </summary>
		public void CheckUndoStack()
		{
            if(UndoStack!=null)
			    while (UndoStack.Count > 20)
				    UndoStack.RemoveAt(0);
		}
		/// <summary>
		/// List of commands in Redo.  This should be cleared anytime a new item is added to the Undo stack.
		/// </summary>
		public ArrayList RedoStack;
		/// <summary>
		/// Takes a command off the top of the redo stack, executes it in Redo mode, then places it onto the Undo stack.
		/// </summary>
		public void Redo()
		{
			if(RedoStack.Count>0)
			{
                if(RedoStack[RedoStack.Count-1].GetType().IsSubclassOf(typeof(Command)))
                {
                    ((Command)RedoStack[RedoStack.Count-1]).Redo();
                    Pb.Invalidate();
                }
                else
                {
				    ArrayList action = (ArrayList)RedoStack[RedoStack.Count-1];
				    ExecuteAction(true, action, true);
                }
                UndoStack.Add(RedoStack[RedoStack.Count-1]);
                RedoStack.RemoveAt(RedoStack.Count-1);
			}
		}
		/// <summary>
		/// Takes a command off the top of the undo stack, executes it in Undo mode, then places it onto the Undo stack.
		/// </summary>
		public void Undo()
		{
			if(UndoStack.Count>0)
			{
                if(UndoStack[UndoStack.Count-1].GetType().IsSubclassOf(typeof(Command)))
                {
                    ((Command)UndoStack[UndoStack.Count-1]).Undo();
                    Pb.Invalidate();
                }
                else
                {
                    ArrayList action = (ArrayList)UndoStack[UndoStack.Count-1];
                    ExecuteAction(false,action,true);
                }
                RedoStack.Add(UndoStack[UndoStack.Count-1]);
                UndoStack.RemoveAt(UndoStack.Count-1);
			}
		}
		/// <summary>
		/// Executes an action in normal mode if redo is true, executes the reverse of the action (to support Undo())
		/// if redo is false.
		/// </summary>
		/// <param name="redo">bool  True for redo mode, false for undo mode.</param>
		/// <param name="action">ArrayList  The macro definition of the action.  The first element is a short integer
		/// that denotes the command to be executed.  The second element is an array list of parameters that are
		/// needed in the parameter list of the macro's associated function call.</param>
		public void ExecuteAction(bool redo, ArrayList action, bool causesInvalidation)
		{
			//	Set this to true on entry, false on exit.
			this.Tv_AfterSelect_SuppressUndoMacro=true;

			CheckUndoStack();

			//	Make sure that LinkMode is off.
			if(Ptool.LinkMode)
				Ptool.ToggleLinkMode();

            if(action[0].GetType()==typeof(int))
            {
                int command = (int)action[0];		//	The command
                switch(command)
                {
                    #region 109 (Pull out of a link)
                    case (109):
	                {
		                //	(109)	Unlink a VertexF vf from the PathF pf
		                //  (VertexF vf, PathF pf, int ind, PolygonFlist toSwallow, <EdgePairArray bustedEdges> )
		                VertexF vf = (VertexF)action[1];
		                PathF pf = (PathF)action[2];
		                int ind = (int)action[3];
    					
		                if(redo)
		                {
			                //	Swallowing requires doubly linking two lists.
			                PolygonFlist toSwallow = (PolygonFlist)action[4];		//	Reverse toSwallow and toUnswallow
			                PolygonF activePoly = Opd.ActivePoly;
    						
			                if(toSwallow != null)
			                {
				                for(int i=0; i<toSwallow.Count; i++)
				                {
					                activePoly.Swallowed.Add(toSwallow[i]);
					                toSwallow[i].SwallowedBy = activePoly;
				                }
			                }

			                pf.RemoveAt(ind);
			                if(pf.GetType()==typeof(PolygonF))
                            {
                                vf.Polygons.Remove(pf);
				                ((PolygonF)pf).AfterRemoveVertexF(ind, vf, Ptool.GetBitmap(pf), Ptool.GetColor(pf));
                                //	Keep track of busted edges after linking
                                if(action.Count<=5)
                                    action.Add( ((PolygonF)pf).ValidateEdges() );
                                else
                                    action[5] = ((PolygonF)pf).ValidateEdges();
                            }
                            else
                            {
                                vf.Contours.Remove(pf);
                                //	Keep track of busted edges after linking
                                if(action.Count<=5)
                                    action.Add(null);
                                else
                                    action[5] = null;
                            }

			                Ptool.UpdateVertexDraw();
							Ptool.UpdateInactivePaths();
		                }
		                else
		                {
			                //	Swallowing requires doubly linking two lists.
			                PolygonFlist toUnswallow = (PolygonFlist)action[4];		//	Reverse toSwallow and toUnswallow
			                PolygonF activePoly = Opd.ActivePoly;
			                if(toUnswallow != null)
			                {
				                for(int i=0; i<toUnswallow.Count; i++)
				                {
					                activePoly.Swallowed.Remove(toUnswallow[i]);
					                toUnswallow[i].SwallowedBy = null;
				                }
			                }
			                pf.Insert(ind, vf);
			                if(pf.GetType()==typeof(PolygonF))
                            {
                                vf.Polygons.Add(pf);
				                ((PolygonF)pf).AfterAddVertexF(ind, vf, Ptool.GetBitmap(pf), Ptool.GetColor(pf));
                            }
                            else
                                vf.Contours.Add(pf);

			                //	Restore busted edges only on Undo.
			                Opd.RestoreEdges( (EdgeGroupArray)action[5], true );

			                Ptool.UpdateVertexDraw();
							Ptool.UpdateInactivePaths();
		                }
	                } break;
		                #endregion
	                #region 110 (Swallow a set of polygons with the active polygon)
                case(110):
                {
	                //	Swallow a set of polygons with the active polygon.
	                //	( PolygonFlist toSwallow)
	                if(redo)
	                {
		                PolygonF activePoly = Opd.ActivePoly;
		                if(activePoly != null)
		                {
			                PolygonFlist pflist = (PolygonFlist)action[1];
			                for(int i=0; i<pflist.Count; i++)
			                {
				                pflist[i].SwallowedBy = activePoly;
				                if(!activePoly.Swallowed.Contains(pflist[i]))
					                activePoly.Swallowed.Add(pflist[i]);
			                }
		                }
	                }
	                else
	                {
		                ArrayList macro = new ArrayList();
		                macro.Add(111);
		                macro.Add(action[1]);
		                ExecuteAction(true, macro, causesInvalidation);
	                }
                } break;
	                #endregion
	                #region 111 (Unswallow a set of polygons with the active polygon)
                case(111):
                {
	                //	Unswallow a set of polygons with the active polygon.
	                //	( PolygonFlist toSwallow )
	                if(redo)
	                {
		                PolygonF activePoly = Opd.ActivePoly;
		                if(activePoly != null)
		                {
			                PolygonFlist pflist = (PolygonFlist)action[1];
			                for(int i=0; i<pflist.Count; i++)
			                {
				                pflist[i].SwallowedBy = null;
				                int ind = activePoly.Swallowed.IndexOf(pflist[i]);
				                if(ind >= 0)
					                activePoly.Swallowed.RemoveAt(ind);
			                }
		                }
	                }
	                else
	                {
		                ArrayList macro = new ArrayList();
		                macro.Add(110);
		                macro.Add(action[1]);
		                ExecuteAction(true, macro, causesInvalidation);
	                }
                } break;
	                #endregion
	                #region 113 (Categorize an object)
                case(113):
                {
	                //	Categorize an object.  No switching behavior is implicated.
	                //	(113, ObjectCategorizationData dat, FieldInfo categorizationField, int newValue, int oldValue)
	                if(redo)
	                {
		                FieldInfo fi = (FieldInfo)action[2];
		                fi.SetValue(action[1], action[3]);
	                }
	                else
	                {
		                ArrayList macro = new ArrayList();
		                macro.Add(113);
		                macro.Add(action[1]);
		                macro.Add(action[2]);
		                macro.Add(action[4]);	//	Reverse newValue and oldValue
		                macro.Add(action[3]);
		                ExecuteAction(true, macro, causesInvalidation);
	                }
                } break;
	                #endregion
	                #region 130 (Create an Occlusion Bridge)
                case(130):
                {
	                //	Create an occlusion bridge.
	                //	(130, OcclusionBridge created, OcclusionBridge destroyed, <FullEdgeArray bustedEdges> )
	                if(redo)
	                {
		                OcclusionBridge created = (OcclusionBridge)action[1];
		                OcclusionBridge destroyed = (OcclusionBridge)action[2];

		                if(created!=null)
			                created.Pf1.Owner.Bridges.Add(created);
		                if(destroyed!=null)
			                destroyed.Pf1.Owner.Bridges.Remove(destroyed);

		                //	Validate edges
		                EdgeGroupArray bustedEdges = created.Pf1.ValidateEdges();
		                if( action.Count==3 )
			                action.Add(bustedEdges);
		                else
			                action[3] = bustedEdges;
	                }
	                else
	                {
		                OcclusionBridge created = (OcclusionBridge)action[1];
		                OcclusionBridge destroyed = (OcclusionBridge)action[2];

		                if(created!=null)
		                {	
			                //	Remove the bridge.
			                created.Pf1.Owner.Bridges.Remove(created);
											
			                //	Recalculate edges where necessary.
			                created.Pf1.CalcEdges();
			                if(created.Pf2!=created.Pf1)
				                created.Pf2.CalcEdges();
		                }
		                if(destroyed!=null)
		                {
			                //	Add the bridge
			                destroyed.Pf1.Owner.Bridges.Add(destroyed);
														
			                //	Recalculate edges where necessary.
			                if(created!=null)
			                {
				                if(destroyed.Pf1!=created.Pf1 && destroyed.Pf1!=created.Pf2)
					                destroyed.Pf1.CalcEdges();
				                if(destroyed.Pf2!=created.Pf1 && destroyed.Pf2!=created.Pf2
					                && destroyed.Pf1!=destroyed.Pf2)
					                destroyed.Pf2.CalcEdges();
			                }
			                else
			                {
				                destroyed.Pf1.CalcEdges();
				                if(destroyed.Pf2!=destroyed.Pf1)
					                destroyed.Pf2.CalcEdges();
			                }
		                }

		                //	Restore busted edges
		                if(action.Count>3)
			                Opd.RestoreEdges( (EdgeGroupArray)action[3], true );
	                }
                } break;
	                #endregion
	                #region 131 (Destroy an Occlusion Bridge)
                case(131):
                {
	                //	Create an occlusion bridge.
	                //	(131, OcclusionBridge destroyed, <FullEdgeArray bustedEdges>)
	                if(redo)
	                {
		                OcclusionBridge destroyed = (OcclusionBridge)action[1];
		                if(destroyed!=null)
		                {
			                destroyed.Pf1.Owner.Bridges.Remove(destroyed);
			                //	Validate edges
			                EdgeGroupArray bustedEdges = destroyed.Pf1.ValidateEdges();
			                if( action.Count==2 )
				                action.Add(bustedEdges);
			                else
				                action[2] = bustedEdges;
		                }
	                }
	                else
	                {
		                OcclusionBridge destroyed = (OcclusionBridge)action[1];
		                if(destroyed!=null)
		                {
			                destroyed.Pf1.Owner.Bridges.Add(destroyed);

			                //	Restore busted edges
			                if(action.Count>3)
				                Opd.RestoreEdges( (EdgeGroupArray)action[3], true );

			                //	Calculate edges where necessary.
			                destroyed.Pf1.CalcEdges();
			                if(destroyed.Pf2!=destroyed.Pf1)
				                destroyed.Pf2.CalcEdges();
		                }
	                }
                } break;
	                #endregion
	                default:
	                {
		                //	Unrecognized command.
		                MessageBox.Show(this,
			                "Attempt to execute an unrecognized command with maco number "
			                + Convert.ToString(command)+".", "Programmer error." );
	                } break;
                }
            }
            else
            {
                Command com = (Command)action[0];
                if( redo )
                    com.Redo();
                else
                    com.Undo();
            }
			//	Set this to false on exit.
			this.Tv_AfterSelect_SuppressUndoMacro=false;

			//	Invalidate the Pb
			Pb.Invalidate();
		}
        private void mUndo_Click(object sender,System.EventArgs e)
        {
            Undo();
        }
        private void mRedo_Click(object sender,System.EventArgs e)
        {
            Redo();
        }
		#endregion
		#region Bitmaps, Core Pixels, ClearBitmaps, and PaintBitmaps
		/// <summary>
		/// For displaying the NaN values.
		/// </summary>
		public Bitmap NanBmp=null;
		/// <summary>
		/// This is the normal display bitmap to be used while displaying this ObjectParser file.
		/// Normally, this is equal to Bmp.  However, when viewing the output of Log-Gabor Filters,
		/// Bmp is set to a different image.  This variable exists so that Bmp can be reset to
		/// DisplayBmp after the Log-Gabor session is over.
		/// </summary>
		public Bitmap DisplayBmp=null;
		/// <summary>
		/// This is the bitmap from the main project.  It is a 32 bpp version of BmpOrig.
		/// </summary>
		public Bitmap Bmp;
		/// <summary>
		/// Contains the highlights for the current object.
		/// </summary>
		public Bitmap BmpCurrentObj;
		/// <summary>
		/// Contains the highlights for all objects.
		/// </summary>
		public Bitmap BmpOtherObj;
		/// <summary>
		/// The image of non-category objects within the pixel exclude scope.
		/// </summary>
		public Bitmap BmpNonObj;
		/// <summary>
		/// The core image pixels (if loaded), null if not loaded.
		/// </summary>
		public Ushort3 CorePixels=null;
		public void LoadNanBitmap()
		{
			if(CorePixels==null)
				LoadCorePixels();
			if(NanBmp==null || NanBmp.Width!=CorePixels.Nj || NanBmp.Height!=CorePixels.Ni)
				NanBmp = new Bitmap(CorePixels.Nj, CorePixels.Ni);
			int i,j;
			int[] col = new int[3];
            unsafe
            {
                BitmapData bd = NanBmp.LockBits(new Rectangle(0, 0, CorePixels.Nj, CorePixels.Ni),
                    ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
                byte* pix;
                int stride = bd.Stride, str;
                int scan0 = bd.Scan0.ToInt32();
                for (i = 0; i < CorePixels.Ni; i++)
                {
                    str = i * stride;
                    for (j = 0; j < CorePixels.Nj; j++)
                    {
                        pix = (byte*)(str + 4 * j) + scan0;
                        if (CorePixels[i, j, 2] == 4095u)
                            *pix = 0xFF;
                        else
                            *pix = 0x00;
                        if (CorePixels[i, j, 1] == 4095u)
                            *(pix + 1) = 0xFF;
                        else
                            *(pix + 1) = 0x00;
                        if (CorePixels[i, j, 0] == 4095u)
                            *(pix + 2) = 0xFF;
                        else
                            *(pix + 2) = 0x00;
                        *(pix + 3) = 0xFF;
                    }
                }
                NanBmp.UnlockBits(bd);
            }
		}
		public void LoadCorePixels()
		{
			string name = Opd.Imagename;
			if(File.Exists(name))
			{
				try
				{
					int errMsg;
					CorePixels = Ushort3.FromPng16(name, out errMsg);
					if(errMsg > 0)
					{
						string msg = "Unspecified error.";
						switch(errMsg)
						{
							case 1:	msg = "Library error";	break;
							case 2:	msg = "Invalid pixel format";	break;
							case 3: msg = "Memory allocation"; break;
							case 4: msg = "Invalid size"; break;
							case 5: msg = "Invalid bitmap handle"; break;
							case 6: msg = "Windows API error"; break;
							case 7: msg = "Error opening image file"; break;
							case 8: msg = "Unsupported file format"; break;
							case 9: msg = "Invalid BMG image"; break;
							case 10: msg = "Invalid file extension"; break;
							case 11: msg = "Error reading file"; break;
							case 12: msg = "Error writing file"; break;
							case 13: msg = "Invalid GeoTIFFPointer"; break;
							case 14: msg = "Undefined BG Image"; break;
							case 15: msg = "BG Image too small"; break;
							case 16: msg = "Corrupt file"; break;
						}
						msg = "Failed to open " + name + ".  Error message " + errMsg.ToString() + " was given:  " + msg;
						MessageBox.Show(msg);
						throw new ApplicationException(msg);
					}
					Opd.ImageWidth = CorePixels.Nj;
					Opd.ImageHeight = CorePixels.Ni;
				}
				catch
				{
					MessageBox.Show("Failed attempt to load core pixels as a 16-bit PNG file.  Loading as a normal image file.");
					CorePixels = Ushort3.FromImage(name);
					Opd.ImageWidth = CorePixels.Nj;
					Opd.ImageHeight = CorePixels.Ni;
				}
			}
			else if (MessageBox.Show(name + " was not found.  Find a new core image file?", "Core image file not found." ,MessageBoxButtons.YesNo)	==  DialogResult.Yes)
			{
				if(OfdNewProjectFromImage==null)
					OfdNewProjectFromImage = new OpenFileDialog();
				OfdNewProjectFromImage.Filter = 
					"PNG |*.png|"+
					"BMP |*.bmp|"+
					"GIF |*.gif|"+
					"JPEG |*.jpg|"+
					"TIFF |*.tif|" + 
					"DCR |*.dcr";
				if(OfdNewProjectFromImage.ShowDialog()==DialogResult.OK)
				{
					name = OfdNewProjectFromImage.FileName;
					Opd.Imagename = name;
					int errmsg;
					CorePixels = Ushort3.FromPng16(name, out errmsg);
					Opd.ImageWidth = CorePixels.Nj;
					Opd.ImageHeight = CorePixels.Ni;
				}
			}
		}
		/// <summary>
		/// Loads core pixels in milliwatts per steridian per square meter.
		/// </summary>
		public void LoadCorePixelsFloat()
		{
			if(CorePixels==null)
			LoadCorePixels();
			int iLen=CorePixels.Ni, jLen=CorePixels.Nj, kLen=CorePixels.Nk;
			CorePixelsFloat = new float[ iLen, jLen, kLen ];

			if(Opd.Fstop==0.0 || Opd.ShutterRate==0.0 || Opd.IsoFilmSpeed==0.0)
			{
				MessageBox.Show(this, "Unspecified Fstop, Shutter rate, and Film speed.  Assuming all are equal to 1.");
				
				int i,j,k;
				for(i=0; i<iLen; i++)
					for(j=0; j<jLen; j++)
						for(k=0; k<kLen; k++)
							CorePixelsFloat[i,j,k]=(float)CorePixels[i,j,k]*1000.0f;
			}
			else
			{
				float fac = Opd.PixelFactor;
				int i,j,k;
				for(i=0; i<iLen; i++)
					for(j=0; j<jLen; j++)
						for(k=0; k<kLen; k++)
							CorePixelsFloat[i,j,k]=(float)CorePixels[i,j,k] * fac;	//	*1000 for milliwatts, not watts.
			}
		}
		public float[,,] CorePixelsFloat;
		#endregion
		#region Pb<-->Img
		/// <summary>
		/// Denotes the pixel locations on the rectangle of the bitmap being represented in the image.
		/// UpdateZoom adjusts this automatically.
		/// </summary>
		protected RectangleF ImgRect;
		/// <summary>
		/// Each time ImgRect is changed, ImgRectChangeCt is incremented.  PolygonF objects will then be able to take note of the
		/// counter value that existed on their most recent update to determine if a new update is needed.
		/// </summary>
		public uint ImgRectChangeCt=2u;
		public uint GetImgRectChangeCt(){ return ImgRectChangeCt; }
		/// <summary>
		/// Implements the IFormParse interface.  Returns the width of Image Bmp (or -1 if Bmp is null).
		/// </summary>
		/// <returns></returns>
		public int GetDisplayImageWidth()
		{
			if(Bmp != null)
				return Bmp.Width;
			return -1;
		}
		/// <summary>
		/// Implements the IFormParse interface.  Returns the height of Image Bmp (or -1 if Bmp is null).
		/// </summary>
		/// <returns></returns>
		public int GetDisplayImageHeight()
		{
			if(Bmp != null)
				return Bmp.Height;
			return -1;
		}
		/// <summary>
		/// Two values that define the zooming flow location of the image (where the mouse pointer is) in Image coordinates (relative to the Bmp).
		/// </summary>
		public PointF ImgZoomFlow;
		/// <summary>
		/// The size of the Pb Control (used to reshape and rescale the ImgRect when Pb is resized).
		/// </summary>
		public Size PbSize;
		public float PbToImgX(float x)
		{
			return x * ImgRect.Width / (float)Pb.Width + ImgRect.Left;
		}
		public float PbToImgY(float y)
		{
			return y * ImgRect.Height / (float)Pb.Height + ImgRect.Top;
		}
		public PointF PbToImg(PointF pt)
		{
			return new PointF(PbToImgX(pt.X), PbToImgY(pt.Y));
		}
		public PointF PbToImg(VertexF vf)
		{
			return new PointF(PbToImgX(vf.X), PbToImgY(vf.Y));
		}
		public float ImgToPbX(float x)
		{
			return (x-ImgRect.Left) * (float)Pb.Width / ImgRect.Width;
		}
		public float ImgToPbY(float y)
		{
			return (y-ImgRect.Top) * (float)Pb.Height / ImgRect.Height;
		}

		public void ImgToPb(PointF[] pts)
		{
			for(int i=0; i<pts.Length; i++)
				pts[i] = ImgToPb(pts[i]);
		}
		public PointF ImgToPb(PointF pt)
		{
			return new PointF(ImgToPbX(pt.X), ImgToPbY(pt.Y));
		}
		public PointF ImgToPb(VertexF vf)
		{
			return new PointF(ImgToPbX(vf.X), ImgToPbY(vf.Y));
		}
		public Rectangle ImgToPbRect(RectangleF rect)
		{
			float l,r,t,b;
			l = ImgToPbX(rect.Left);
			r = ImgToPbX(rect.Right);
			t = ImgToPbY(rect.Top);
			b = ImgToPbY(rect.Bottom);
			int il = (int)(l+0.5f);
			int it = (int)(t+0.5f);
			return new Rectangle(il,it,(int)(r+0.5f)-il,(int)(b+0.5f)-it);
		}
		public RectangleF ImgToPbRectF(RectangleF rect)
		{
			float l,r,t,b;
			l = ImgToPbX(rect.Left);
			r = ImgToPbX(rect.Right);
			t = ImgToPbY(rect.Top);
			b = ImgToPbY(rect.Bottom);
			return new RectangleF(l,t,r-l,b-t);
		}
		public RectangleF PbToImgRect(Rectangle rect)
		{
			float l,r,t,b;
			l = PbToImgX((float)rect.Left);
			r = PbToImgX((float)rect.Right);
			t = PbToImgY((float)rect.Top);
			b = PbToImgY((float)rect.Bottom);
			return new RectangleF(l,t,r-l,b-t);
		}
		public Rectangle InvPbRect( Rectangle r )
		{
			return r;
			/*
			double c = (double)Pb.Width/(double)ImgRect.Width;		//	Compute the compression ratio.
			
			if(c<1.0) return r;
			double x0, x1, y0, y1;
			x0 = (double)r.X;
			y0 = (double)r.Y;
			x1 = (double)r.Right;
			y1 = (double)r.Bottom;
			x0 = (Math.Floor(x0/c))*c;
			y0 = (Math.Floor(y0/c))*c;
			x1 = (Math.Ceiling(x1/c))*c;
			y1 = (Math.Ceiling(y1/c))*c;
			return new Rectangle((int)x0, (int)y0, (int)(x1-x0)+1, (int)(y1-y0)+1);
			*/
		}
		
		public PointF[] PolyToPointTable(PolygonF pf)
		{
			PointF[] output = new PointF[pf.Count];
			PathToPointTable(pf, output);
			return output;
		}
		public void PathToPointTable(PathF pf, PointF[] initializedOutput)
		{
			for(int i=0; i<initializedOutput.Length; i++)
				initializedOutput[i] = ImgToPb(pf[i]);
		}
		public void ImgToPb(PointF[] input, PointF[] initializedOutput)
		{
			for(int i=0; i<initializedOutput.Length; i++)
				initializedOutput[i] = ImgToPb(input[i]);
		}
		public void ImgToPb(ContourF input, PointF[] initializedOutput)
		{
			for(int i=0; i<initializedOutput.Length; i++)
				initializedOutput[i] = ImgToPb(input[i]);
		}
		#endregion
		#region Tools, Utilities, Cursors
		/// <summary>
		/// The default polygon tool.
		/// </summary>
		public PathTool Ptool;
		/// <summary>
		/// True if an active occlusion bridge is currently specified.
		/// </summary>
		public bool CanHack
		{
			get
			{
				return ActiveBridge!=null;
			}
		}
		/// <summary>
		/// Gets an active occlusion bridge if one exists.  If no bridge exists, returns null.
		/// An active occlusion bridge is part of the active object, intersects the active polygon,
		/// at the currently active vertex.
		/// </summary>
		public OcclusionBridge ActiveBridge
		{
			get
			{
				PolygonF actPoly = Opd.ActivePoly;
				if(actPoly!=null && actPoly.Count>2 && CurrentTool==ToolType.Polygon && !Ptool.LinkMode)
				{
					ParsedObject po = actPoly.Owner;
					//	Check to see if a bridge should be destroyed
					OcclusionBridge actBridge = null;
					for(int i=0; i<po.Bridges.Count; i++)
					{
						actBridge = po.Bridges[i];
						if( actBridge.Vf1==Ptool.ImgLeg[0] || actBridge.Vf2==Ptool.ImgLeg[0] )
							return actBridge;
					}
				}
				return null;
			}
		}
		/// <summary>
		/// Recalculate the way the tool draws stuff based on Opd.  Call this when something has changed in Opd.
		/// </summary>
		public void ResetTool()
		{
			if(CurrentTool==ToolType.Polygon || CurrentTool==ToolType.Contour)
			{
				Ptool.UpdateVertexDraw();
				Ptool.UpdateInactivePaths();
			}
		}
		public bool CursorHidden;
		public void HideCursor()
		{
			if(!CursorHidden) Cursor.Hide();
			CursorHidden=true;
		}
		public void ShowCursor()
		{
			if(CursorHidden) Cursor.Show();
			CursorHidden=false;
		}

		public bool CursorInPb()
		{
			Point p = Pb.PointToClient(Cursor.Position);
			if(p.X<0 || p.Y<0 || p.X>=Pb.Width || p.Y>=Pb.Height) return false;
			else return true;
		}
		
		#endregion
		#region DragDrop
		private static bool ObjectParserBinaryDragFile(IDataObject data)
		{
			if(data.GetDataPresent("FileNameW"))
			{
				object o = data.GetData("FileDrop");
				string[] dirs = (string[]) o;
                
				if(dirs.Length > 0)
                    if(dirs[0].ToUpper().EndsWith(".OBJPARSER"))
                        if(File.Exists(dirs[0]))
							return true;
			}
			return false;
		}
        private static bool ObjectParserXmlDragFile(IDataObject data)
        {
            if(data.GetDataPresent("FileNameW"))
            {
                object o = data.GetData("FileDrop");
                string[] dirs = (string[])o;

                if(dirs.Length > 0)
                    if(dirs[0].ToUpper().EndsWith(".OBJPARSER.XML"))
                        if(File.Exists(dirs[0]))
                            return true;
            }
            return false;
        }
        private static bool ObjectParserSoapDragFile(IDataObject data)
        {
            if(data.GetDataPresent("FileNameW"))
            {
                object o = data.GetData("FileDrop");
                string[] dirs = (string[])o;

                if(dirs.Length > 0)
                    if(dirs[0].ToUpper().EndsWith(".OBJPARSER.SOAP"))
                        if(File.Exists(dirs[0]))
                            return true;
            }
            return false;
        }
		private static bool ImageDragFile(IDataObject data)
		{
			if(data.GetDataPresent("FileNameW"))
			{
				object o = data.GetData("FileDrop");
				string[] dirs = (string[]) o;
				
				if(dirs.Length > 0)
                {
                    string fname = dirs[0].ToUpper();
					if(	fname.EndsWith(".PNG") ||
						fname.EndsWith(".BMP") ||
						fname.EndsWith(".GIF") ||
						fname.EndsWith(".JPG") ||
						fname.EndsWith(".TIF") ||
						fname.EndsWith(".DCR") )
						if(File.Exists(fname))
							return true;
                }
			}
			return false;
		}
		private void FormParse_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)
		{
            if(ObjectParserBinaryDragFile(e.Data) || ObjectParserXmlDragFile(e.Data) || ImageDragFile(e.Data))
				e.Effect = DragDropEffects.Copy;
		}
		private void FormParse_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
		{
			if( ObjectParserBinaryDragFile(e.Data) )
			{
				e.Effect = DragDropEffects.Copy;
				string[] files = (string[])e.Data.GetData("FileDrop");
				InitializeProject(SerializationType.Binary, files[0]);
				mSave.Enabled = true;
			}
            else if(ObjectParserSoapDragFile(e.Data))
            {
                e.Effect = DragDropEffects.Copy;
                string[] files = (string[])e.Data.GetData("FileDrop");
                InitializeProject(SerializationType.Soap,files[0]);
                mSave.Enabled = true;
            }
            else if(ObjectParserXmlDragFile(e.Data))
            {
                e.Effect = DragDropEffects.Copy;
                string[] files = (string[])e.Data.GetData("FileDrop");
                InitializeProject(SerializationType.Xml,files[0]);
                mSave.Enabled = true;
            }
			else if( ImageDragFile(e.Data) )
			{
				e.Effect = DragDropEffects.Copy;
				string[] files = (string[])e.Data.GetData("FileDrop");
				
				string[] ss = files[0].Split(new char[] {'.'});
				string projname = ss[0];
				for(int i=1; i<ss.Length-1; i++)
					projname = projname + ss[i];
				InitializeProject(projname, files[0], null);
			}
		}

		#endregion
		#region Initializers and Constructors
		/// <summary>
		/// Initially Opd.Projname + ".ObjParser", but user can change the file name.
		/// </summary>
		public string SaveName;
		/// <summary>
		/// True if the project has loaded successfully.
		/// </summary>
		public bool ProjectLoaded;
		/// <summary>
		/// Enables selections in the main menu.
		/// </summary>
		public void EnableMenus()
		{
			this.mFile.Enabled = true;
			this.mHelp.Enabled = true;

			this.mProj.Enabled = ProjectLoaded;
			this.mEdit.Enabled = ProjectLoaded;
			this.mView.Enabled = ProjectLoaded;
			this.mOptions.Enabled = ProjectLoaded;
			//this.mOutput.Enabled = ProjectLoaded;
			this.mTool.Enabled = ProjectLoaded;
		}
		public FormParse()
		{
			InitializeComponent();
			PbRibbon.Height=0;
			ProjectLoaded = false;
			EnableMenus();
			InitTvImages();
		}
		public FormParse(string filename)
		{
			try
			{
				InitializeComponent();
				PbRibbon.Height=0;
				EnableMenus();
				InitTvImages();
				Cursor = Cursors.WaitCursor;
				try
				{
					InitializeProject(ObjectParserData.StypeFromFname(filename), filename);	
					ProjectLoaded = true;
				}
				catch(Exception ex)
				{
					ProjectLoaded = false;
					MessageBox.Show(this, "Object parser could not open the file " + filename +
						" because it generated the following exception:  " + ex.Message);
				}
			}
			finally
			{
				Cursor = Cursors.Arrow;
			}
		}
		/// <summary>
		/// Initializes the project.
		/// </summary>
		/// <param name="filetype">int  if filetype = 1, ObjParser binary file, if filetype = 0, Xml type.</param>
		/// <param name="projname">string  The name of the project without the file extension.</param>
		/// <param name="imagename">string  The name of the image file with the extension.</param>
		/// <param name="displayImagename"></param>
		public void InitializeProject(string projname, string imagename, string displayImagename)
		{
			//	Initialize the data structure.
			Opd = new ObjectParserData(imagename, displayImagename, this);
			//	Pixels from the core part of the image.
			CorePixels = null;
			if(displayImagename != null)
			{
				DisplayBmp = Bmp = new Bitmap(displayImagename);//	Initialize the original bitmap image.
				Opd.ImageWidth = Bmp.Width;
				Opd.ImageHeight = Bmp.Height;
			}
			else
			{
				DisplayBmp = Bmp = new Bitmap(imagename);//	Initialize the original bitmap image.
				Opd.ImageWidth = Bmp.Width;
				Opd.ImageHeight = Bmp.Height; 
			}
			//Bmp = UnsafeSupport.OpenBitmap(imagename);
			Opd.Projname = projname;
			SaveName = projname + ".ObjParser";
			Init2();
			Init4();
		}
		public void InitializeProject(SerializationType stype, string fname)
		{
			Opd = ObjectParserData.Deserialize(fname, this, stype);

            //  Handle edges of an old format where junctions could be affected by ContourF objects.
            if( !Opd.EdgesMerged )
            {
                this.Opd.RootCategory.MergeEdges(true);
                Opd.EdgesMerged = true;
            }

			//	Pixels from the core part of the image.
			CorePixels = null;

			bool proceed = false;
			Exception exLog=null;
			
			try
			{
				if(Opd.DisplayImagename != null && Opd.DisplayImagename.Length>0)
				{
					DisplayBmp = Bmp = new Bitmap(Opd.DisplayImagename);
                    if (Bmp.PixelFormat != PixelFormat.Format32bppArgb)
                    {
                        DisplayBmp = Bmp = Bmp.Clone(new Rectangle(0, 0, Bmp.Width, Bmp.Height), PixelFormat.Format32bppArgb);
                    }
					Opd.ImageWidth = Bmp.Width;
					Opd.ImageHeight = Bmp.Height;
				}
				else
				{
                    DisplayBmp = Bmp = new Bitmap(Opd.Imagename);
                    if (Bmp.PixelFormat != PixelFormat.Format32bppArgb)
                    {
                        DisplayBmp = Bmp = Bmp.Clone(new Rectangle(0, 0, Bmp.Width, Bmp.Height), PixelFormat.Format32bppArgb);
                    }
					Opd.ImageWidth = Bmp.Width;
					Opd.ImageHeight = Bmp.Height;
				}
				proceed = true;
			}
			catch(Exception ex)
			{
				exLog = ex;
				// Display a MsgBox asking the user to save changes or abort.
				string name = Opd.Imagename;
				if(Opd.DisplayImagename != null)
				{
					name = Opd.DisplayImagename;
					if(MessageBox.Show(name + " was not found.  Find a new display file?", "Image display file not found." ,MessageBoxButtons.YesNo)	==  DialogResult.Yes)
					{
						if(OfdNewProjectFromImage==null)
							OfdNewProjectFromImage = new OpenFileDialog();
						OfdNewProjectFromImage.Filter = 
							"PNG |*.png|"+
							"BMP |*.bmp|"+
							"GIF |*.gif|"+
							"JPEG |*.jpg|"+
							"TIFF |*.tif|" + 
							"DCR |*.dcr";
						if(OfdNewProjectFromImage.ShowDialog()==DialogResult.OK)
						{
							Opd.DisplayImagename = OfdNewProjectFromImage.FileName;
							DisplayBmp = Bmp = new Bitmap(Opd.DisplayImagename);
							Opd.ImageWidth = Bmp.Width;
							Opd.ImageHeight = Bmp.Height;
							proceed = true;
						}
					}
				}
				else
				{
					name = Opd.Imagename;
					if(MessageBox.Show(name + " was not found.  Find a new core image file?", "Core image file not found." ,MessageBoxButtons.YesNo)	==  DialogResult.Yes)
					{
						if(OfdNewProjectFromImage==null)
							OfdNewProjectFromImage = new OpenFileDialog();
						OfdNewProjectFromImage.Filter = 
							"PNG |*.png|"+
							"BMP |*.bmp|"+
							"GIF |*.gif|"+
							"JPEG |*.jpg|"+
							"TIFF |*.tif|" + 
							"DCR |*.dcr";
						if(OfdNewProjectFromImage.ShowDialog()==DialogResult.OK)
						{
							name = OfdNewProjectFromImage.FileName;
							Opd.Imagename = name;
							DisplayBmp = Bmp = new Bitmap(name);
							Opd.ImageWidth = Bmp.Width;
							Opd.ImageHeight = Bmp.Height;
							proceed = true;
						}
					}
				}
			}
			if(proceed)
			{
				Init2();
				//PaintBitmaps(Opd.ActiveCategory.PixExcludeNode);
				Init4();
			}
			else
			{
				MessageBox.Show(this, "ObjectParser could not start because the following error occurred:  "
					+ exLog.Message);
			}
		}
		public void Init2()
		{
			//	Get rid of CorePixels
			CorePixels=null;
			CorePixelsFloat=null;

            //  If the log-gabor form is open, update it.
			if(Flg!=null)
			{
				LoadCorePixelsFloat();
				Flg.OnNewProjectLoaded();
			}

			//	Event handler.
			this.PbRibbon.ImgRectChanged+=new EventHandler(PbRibbon_ImgRectChanged);

			//	Title the window with the name of the project.
			this.Text = Opd.ShortProjname + "| " + Opd.Projname;

			//	Cursor in "wait" mode
			Cursor lastCursor = Cursor.Current;
			Cursor.Current = Cursors.WaitCursor;

			ImgRectChangeCt = 0u;

			//	Initialize the supporting bitmaps.
			BmpCurrentObj = new Bitmap(Bmp.Width, Bmp.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
			BmpOtherObj = new Bitmap(Bmp.Width, Bmp.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
			BmpNonObj = new Bitmap(Bmp.Width, Bmp.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
			Rectangle r = new Rectangle(0,0,Bmp.Width,Bmp.Height);

			//	If the bitmap is not 32bpp, then make it so.

            if (Bmp.PixelFormat != PixelFormat.Format32bppArgb)
			{
				Bmp = Bmp.Clone(new Rectangle(0,0,Bmp.Width,Bmp.Height), PixelFormat.Format32bppArgb);
				//for(int i=0; i<bmp.Width; i++)
				//	for(int j=0; j<bmp.Height; j++)
				//		Bmp.SetPixel(i,j,bmp.GetPixel(i,j));
			}
			InitZoom();	//	Initialize the zoom control.
			PbSize = new Size(Pb.Width,Pb.Height);	//	Record the size of the picture-box.
			Pb.Invalidate();	//	Trigger a paint event on the picture box.
			ProjectLoaded = true;	//	Denote that the project was loaded successfully.
			EnableMenus();	//	Toggle the menu enablement.

			CursorHidden=false;
			UndoStack = new ArrayList();
			RedoStack = new ArrayList();

			Cursor.Current = lastCursor;
		}
		public void Init4()
		{
			object actThing = Opd.ActiveThing;
            CurrentSelection = new SelectionRecord(actThing,this);
			if(actThing.GetType()==typeof(ContourF))
			{
				ContourF con = (ContourF)actThing;
				con.PolyOwner.CalcEdges();
			}
			else if(actThing.GetType()==typeof(PolygonF))
			{
				((PolygonF)actThing).CalcEdges();
			}
			RefreshTv();
            TreeNode tn = NodeAttachedTo(actThing);
            tn.EnsureVisible();
            Tv.SelectedNode = tn;
            CurrentSelection.SelNode = tn;
            SelectionRecord.PaintBitmaps(Opd.RootCategory,CurrentSelection,this);

            //  Update the tool
            Ptool = new PathTool(this);
            pbTool.Invalidate();
            if(CurrentSelection.SelThing==null)
                CurrentTool = ToolType.None;
            else if(CurrentSelection.SelThing.GetType()==typeof(PolygonF))
                CurrentTool = ToolType.Polygon;
            else if(CurrentSelection.SelThing.GetType()==typeof(ContourF))
                CurrentTool = ToolType.Contour;
            else if(CurrentSelection.SelThing.GetType()==typeof(Circle))
                CurrentTool = ToolType.Circle;
            else
                CurrentTool = ToolType.None;
		}
		/// <summary>
		/// Initializes the ImgRect.
		/// </summary>
		public void InitZoom()
		{
			InitZoom(new Rectangle(0,0,Bmp.Width, Bmp.Height));
		}
		public void InitZoom(Rectangle encompassed)
		{
			ImgRectChangeCt++;
			//	Initialize the zoom situation.
			PointF pt = new PointF(encompassed.Left+encompassed.Width/2, encompassed.Top+encompassed.Height/2);
			float wScale = (float)Pb.Width/(float)encompassed.Width;
			float hScale = (float)Pb.Height/(float)encompassed.Height;
			float w,h;
			float whRatio = wScale/hScale;
			if (whRatio<1.0)	//	Width is the limiting reagent
			{
				w = (float)encompassed.Width;
				h = (float)encompassed.Height/whRatio;
			}
			else
			{
				w = (float)encompassed.Width*whRatio;
				h = (float)encompassed.Height;
			}
			ImgRect = new RectangleF(pt.X-w/2.0f,pt.Y-h/2.0f,w,h);
		}
		#endregion
		#region Database and Tony
		private void mOutPixColor_Click(object sender, System.EventArgs e)
		{
			sfdOutput.FileName = Opd.Projname.Replace(".ObjParser", ".txt");
			if(sfdOutput.ShowDialog() == DialogResult.OK)
			{
				int errmsg;
				Ushort3 pixelValues=Ushort3.FromPng16(Opd.Imagename, out errmsg);
				
				FileStream txtFile = new FileStream(sfdOutput.FileName, FileMode.Create);
				StreamWriter sw = new StreamWriter(txtFile);

				//	Conform to the ROF output standard
				sw.WriteLine("1.00");
				string[] ss = this.Opd.Imagename.Split('\\', '/');
				sw.WriteLine(ss[ss.Length-1]);
				sw.WriteLine("Source Image Size: "
					+ Convert.ToString(pixelValues.Nj) + ", "
					+ Convert.ToString(pixelValues.Ni));
				sw.WriteLine( "Category: " + Enum.GetName(typeof(ImageCategory), Opd.ImageCat.ImageCategory) );
				sw.WriteLine( "Descriptors: " + Opd.CatText.Replace("\n", "; ") );
				sw.WriteLine( "NumObjects: " + Convert.ToString(Opd.NumObjects) );
				WriteNodeToPixColor(Opd.RootCategory, sw, Opd.ActiveObject, pixelValues);
				sw.Close();				
			}
		}
		public static void WriteNodeToPixColor(CategoryNode cn, StreamWriter sw, ParsedObject currentlyActiveObject, Bitmap bmp)
		{
			if(cn != null && cn.Name.ToUpper() != "RESIDUE")
			{
				//	A couple of important objects.
				ParsedObject od;
				ParsedObject cnActObj = cn.ActiveObject;

				//	Pixel color.
				Color col;
			
				Rectangle clipRect = new Rectangle(0, 0, bmp.Width-1, bmp.Height-1);
			
				//	Write the pixels for each object within the category.
				for(int i=0; i<cn.Objects.Count; i++)
				{
					od = (ParsedObject)cn.Objects[i];

					ArrayList buffer = new ArrayList();
					buffer.Add("NameLength: " + Convert.ToString(((ParsedObject)cn.Objects[i]).Name.Length) + " " + ((ParsedObject)cn.Objects[i]).Name);
					buffer.Add("Category: " + od.Category.Name);
					buffer.Add( "Descriptors: " + od.OutputText.Replace("\n", "; ") );
					buffer.Add("nRows: ");
					for(int polyCt=0; polyCt<od.Polygons.Count; polyCt++)
					{
						od.Polygons[polyCt].Pix.Clip(clipRect);
						for(int k=od.Polygons[polyCt].Pix.Top; k<=od.Polygons[polyCt].Pix.Bottom; k++)
						{
							ArrayList buffer2 = new ArrayList();
							buffer2.Add("Row y: "+Convert.ToString(k)+" nPels: ");

							for(int j=od.Polygons[polyCt].Pix.Left; j<=od.Polygons[polyCt].Pix.Right; j++)
							{
								if(od.Polygons[polyCt].Pix.PixelIsTagged(j,k))
								{
									col = bmp.GetPixel(j,k);

									buffer2.Add("x: " + Convert.ToString(j) + " - "
										+ Convert.ToString(col.R) + ", "
										+ Convert.ToString(col.G) + ", "
										+ Convert.ToString(col.B) );
								}
							}
							if(buffer2.Count > 1)
							{
								buffer2[0] = ((string)buffer2[0]) + Convert.ToString(buffer2.Count-1);
								buffer.Add(buffer2);
							}
						}
					}
					if(buffer.Count > 4)
					{
						buffer[3] = ((string)buffer[3]) + Convert.ToString(buffer.Count-4);
						for(int j=0; j<buffer.Count; j++)
						{
							if(buffer[j].GetType() == typeof(ArrayList))
							{
								ArrayList a = (ArrayList)buffer[j];
								for(int k=0; k<a.Count; k++)
									sw.WriteLine((string)a[k]);
							}
							else
							{
								sw.WriteLine((string)buffer[j]);
							}
						}
					}
				}
				//	Tree recursion for sub-categories.
				for(int i=0; i<cn.Sub.Count; i++)
					WriteNodeToPixColor((CategoryNode)cn.Sub[i], sw, currentlyActiveObject, bmp);
			}
		}
		public static void WriteNodeToPixColor(CategoryNode cn, StreamWriter sw, ParsedObject currentlyActiveObject, Ushort3 pixelValues)
		{
			if(cn != null && cn.Name.ToUpper() != "RESIDUE")
			{
				//	A couple of important objects.
				ParsedObject od;
				ParsedObject cnActObj = cn.ActiveObject;

				Rectangle clipRect = new Rectangle(0, 0, pixelValues.Ni-1, pixelValues.Nj-1);
			
				//	Write the pixels for each object within the category.
				for(int i=0; i<cn.Objects.Count; i++)
				{
					od = (ParsedObject)cn.Objects[i];

					ArrayList buffer = new ArrayList();
					buffer.Add("NameLength: " + Convert.ToString(((ParsedObject)cn.Objects[i]).Name.Length) + " " + ((ParsedObject)cn.Objects[i]).Name);
					buffer.Add("Category: " + od.Category.Name);
					buffer.Add( "Descriptors: " + od.OutputText.Replace("\n", "; ") );
					buffer.Add("nRows: ");
					for(int polyCt=0; polyCt<od.Polygons.Count; polyCt++)
					{
						od.Polygons[polyCt].Pix.Clip(clipRect);
						for(int k=od.Polygons[polyCt].Pix.Top; k<=od.Polygons[polyCt].Pix.Bottom; k++)
						{
							ArrayList buffer2 = new ArrayList();
							buffer2.Add("Row y: "+Convert.ToString(k)+" nPels: ");

							for(int j=od.Polygons[polyCt].Pix.Left; j<=od.Polygons[polyCt].Pix.Right; j++)
							{
								if(od.Polygons[polyCt].Pix.PixelIsTagged(j,k))
								{
									buffer2.Add("x: " + Convert.ToString(j) + " - "
										+ Convert.ToString(pixelValues[k,j,0]) + ", "
										+ Convert.ToString(pixelValues[k,j,1]) + ", "
										+ Convert.ToString(pixelValues[k,j,2]) );
								}
							}
							if(buffer2.Count > 1)
							{
								buffer2[0] = ((string)buffer2[0]) + Convert.ToString(buffer2.Count-1);
								buffer.Add(buffer2);
							}
						}
					}
					if(buffer.Count > 4)
					{
						buffer[3] = ((string)buffer[3]) + Convert.ToString(buffer.Count-4);
						for(int j=0; j<buffer.Count; j++)
						{
							if(buffer[j].GetType() == typeof(ArrayList))
							{
								ArrayList a = (ArrayList)buffer[j];
								for(int k=0; k<a.Count; k++)
									sw.WriteLine((string)a[k]);
							}
							else
							{
								sw.WriteLine((string)buffer[j]);
							}
						}
					}
				}

				//	Tree recursion for sub-categories.
				for(int i=0; i<cn.Sub.Count; i++)
					WriteNodeToPixColor((CategoryNode)cn.Sub[i], sw, currentlyActiveObject, pixelValues);
			}
		}
		public static DbSource[] DbSources;
		public static DbSource[] DeserializeDbSources()
		{
			string filepath = Application.StartupPath + '\\' + DbSource.FileName;
			if( File.Exists(filepath) )
			{
				BinaryFormatter formatter = new BinaryFormatter();
				Stream stream = new FileStream(filepath, FileMode.Open, System.IO.FileAccess.Read, FileShare.Read);
				DbSource[] output = (DbSource[])formatter.Deserialize(stream);
				stream.Close();
				return output;
			}
			
			return null;
		}

		public int ActiveDbSource=0;
		private void mWilsonOut1_Click(object sender, System.EventArgs e)
		{
			if(OfdBatch==null)
				OfdBatch = new OpenFileDialog();
			OfdBatch.Multiselect = true;
			OfdBatch.Filter = "ObjParser Files | *.ObjParser";
			if(OfdBatch.ShowDialog()==DialogResult.OK)
			{
				string[] fnames = OfdBatch.FileNames;
				if(fnames != null)
				{
					for(int i=0; i<fnames.Length; i++)
					{
						ObjectParserData opd = ObjectParserData.Deserialize(fnames[i], this, SerializationType.Binary);
						statusBar1.Text = opd.ShortProjname;

						int errmsg;
						Ushort3 pixelValues = Ushort3.FromPng16(opd.Imagename, out errmsg);

						FileStream txtFile
							= new FileStream(fnames[i].Replace(".ObjParser", ".txt"), FileMode.Create);
						StreamWriter sw = new StreamWriter(txtFile);

						//	Conform to the ROF output standard
						sw.WriteLine("1.01");
						string[] ss = opd.Imagename.Split('\\', '/');
						sw.WriteLine(ss[ss.Length-1]);
						sw.WriteLine("Source Image Size: "
							+ Convert.ToString(pixelValues.Nj) + ", "
							+ Convert.ToString(pixelValues.Ni));
						sw.WriteLine( "Category: " + Enum.GetName(typeof(ImageCategory), opd.ImageCat.ImageCategory) );
						sw.WriteLine( "Descriptors: " + opd.CatText.Replace("\n", "; ") );
						sw.WriteLine( "NumObjects: " + Convert.ToString(opd.NumObjectsNotResidue) );
						WriteNodeToPixColor(opd.RootCategory, sw, opd.ActiveObject, pixelValues);
						sw.Close();
					}
				}
			}
			this.statusBar1.Text = "Ready.";
		}
		public FolderBrowserDialog FbdBatchBinaryMask;
		public OpenFileDialog OfdBatchBinaryMask;
		private void mBatchBinaryMaskOut_Click(object sender, System.EventArgs e)
		{
			CreateBinaryMasks();
			this.statusBar1.Text = "Ready.";
		}
		/// <summary>
		/// Creates binary masks for polygons and objects.
		/// </summary>
		/// <returns>A string array of file paths and file names.</returns>
		private bool CreateBinaryMasks()
		{
			//	Make a new file browsing dialog (if necessary)
			if(FbdBatchBinaryMask==null)
				FbdBatchBinaryMask = new FolderBrowserDialog();
			//	Label as "fbd" for short.
			FolderBrowserDialog fbd = FbdBatchBinaryMask;

			//	Can make a new folder.
			fbd.ShowNewFolderButton=true;
			//	Instruct the user to specify the output directory.
			fbd.Description="Specify the output directory.";
			//	Show the folder browsing dialog box.
			if(fbd.ShowDialog()==DialogResult.OK && fbd.SelectedPath!=null && fbd.SelectedPath.Length>0)
			{
				//	Get the folder path.
				string path = fbd.SelectedPath;
				//	Make a new open file dialog (if necessary)
				if(OfdBatchBinaryMask==null)
					OfdBatchBinaryMask = new OpenFileDialog();
				//	Label as "ofd" for short.
				OpenFileDialog ofd = OfdBatchBinaryMask;
				//	Enable the ability to select multiple files.
				ofd.Multiselect = true;
				//	Filter for ObjParser files.
				ofd.Filter = "ObjParser Files | *.ObjParser";
				//	Indices for objects and polygons.
				uint uniqueObjectInd=1u;
				uint uniquePolygonInd=1u;
				//	Text output
				ArrayList textOutput = new ArrayList();
				//	Show the folder
				if(ofd.ShowDialog()==DialogResult.OK)
				{
					int i;
					//	Get the selected filenames.
					string[] fnames = ofd.FileNames;
					if(fnames != null)
					{
						//	For each filename
						for(i=0; i<fnames.Length; i++)
						{
							//	Deserialize the file.
                            ObjectParserData opd = ObjectParserData.Deserialize(fnames[i], this, SerializationType.Binary);
							//	Get the short project name
							string projName = opd.ShortProjname;
							statusBar1.Text = projName;
                            //  Get the leaves
                            CategoryNode cn = opd.RootCategory.GetSubRecursive("Leaves");
							//	Assign unique IDs.
							cn.AssignUniqueIds( ref uniqueObjectInd, ref uniquePolygonInd );
							//	Save masks
							cn.SaveMasks(path, textOutput);
						}
						FileStream txtFile
							= new FileStream(path + "\\TableOfContents.txt", FileMode.Create);
						StreamWriter sw = new StreamWriter(txtFile);
						sw.WriteLine(ParsedObject.OutputTextFieldNames);
						for(i=0; i<textOutput.Count; i++)
							sw.WriteLine( (string)textOutput[i] );
						sw.Close();
					}
					return true;
				}
			}
			return false;
		}

		/// <summary>
		/// Creates binary masks for polygons and objects.
		/// </summary>
		/// <param name="source">The database source where the data will be created.</param>
		/// <returns>A string array of file paths and file names.</returns>
		private bool CreateBinaryMasksAndDatabase(DbSource source)
		{
			//	Make a new file browsing dialog (if necessary)
			if(FbdBatchBinaryMask==null)
				FbdBatchBinaryMask = new FolderBrowserDialog();
			//	Label as "fbd" for short.
			FolderBrowserDialog fbd = FbdBatchBinaryMask;

			//	Can make a new folder.
			fbd.ShowNewFolderButton=true;
			//	Instruct the user to specify the output directory.
			fbd.Description="Specify the mask file directory.";
			//	Show the folder browsing dialog box.
			if(fbd.ShowDialog()==DialogResult.OK && fbd.SelectedPath!=null && fbd.SelectedPath.Length>0)
			{
				//	Get the folder path.
				string path = fbd.SelectedPath;
				//	Make a new open file dialog (if necessary)
				if(OfdBatchBinaryMask==null)
					OfdBatchBinaryMask = new OpenFileDialog();
				//	Label as "ofd" for short.
				OpenFileDialog ofd = OfdBatchBinaryMask;
				//	Enable the ability to select multiple files.
				ofd.Multiselect = true;
				//	Filter for ObjParser files.
				ofd.Filter = "ObjParser Files | *.ObjParser";
				//	Indices for objects and polygons.
				//uint uniqueImageInd=1u;
				uint uniqueObjectInd=1u;
				uint uniquePolygonInd=1u;
				//	Show the folder
				if(ofd.ShowDialog()==DialogResult.OK)
				{
					//	Create tables
					ImageDbTable img = new ImageDbTable( source );
					ParsedObjectDbTable po = new ParsedObjectDbTable( source );
					PolygonDbTable poly = new PolygonDbTable( source );

					//	Drop old tables.
					img.DropTableIfExists.ExecuteNonQuery();
					po.DropTableIfExists.ExecuteNonQuery();
					poly.DropTableIfExists.ExecuteNonQuery();

					//	Create new tables.
					img.CreateTable.ExecuteNonQuery();
					po.CreateTable.ExecuteNonQuery();
					poly.CreateTable.ExecuteNonQuery();

					//	Add tables to the DataSet
					source.DbSet.Tables.Clear();
					source.DbSetAdd(img.Table);
					source.DbSetAdd(po.Table);
					source.DbSetAdd(poly.Table);

					//	Get the selected filenames.
					string[] fnames = ofd.FileNames;
					if(fnames != null)
					{
						//	For each filename
						for(int i=0; i<fnames.Length; i++)
						{
							//	Deserialize the file.
                            ObjectParserData opd = ObjectParserData.Deserialize(fnames[i], this, SerializationType.Binary);
							//opd.DbCache_UniqueId = uniqueImageInd++;
							opd.SerializationCt = 0ul;
							opd.Imagename = "..\\CoreImages\\" + Util.RemovePathInfo(opd.Imagename);
							opd.Imagename = FileRelativizor.Absolutize(opd.Projname, opd.Imagename);
							if(opd.DisplayImagename!=null && opd.DisplayImagename!="")
							{
								opd.DisplayImagename = "..\\DisplayImages\\" + Util.RemovePathInfo(opd.DisplayImagename);
								opd.DisplayImagename = FileRelativizor.Absolutize(opd.Projname, opd.DisplayImagename);
								opd.DisplayImagename = opd.DisplayImagename.Replace("_12.png", "_8.png");
							}
							//	Get the short project name
							string projName = opd.ShortProjname;
							statusBar1.Text = projName;
							//	Assign unique IDs.
							opd.RootCategory.AssignUniqueIds( ref uniqueObjectInd, ref uniquePolygonInd );
							opd.RootCategory.SaveMasks(path, null);
							//	Fill the data tables.
							img.AddDataRow(opd);
							opd.RootCategory.AddData(po, poly, 0);
							//	Re-serialize the file
                            opd.Serialize(opd.Projname, false, SerializationType.Binary);
						}
					}
					statusBar1.Text = "Sending info to database.";
					int imgResult = img.InsertAll();
					int poResult = po.InsertAll();
					int polyResult = poly.InsertAll();
					statusBar1.Text = "Ready.";
					return true;
				}
			}
			return false;
		}

		private void mSqlOptions_Click(object sender, System.EventArgs e)
		{
			DbSourceDialog dbd = new DbSourceDialog(ActiveDbSource);
			dbd.ShowDialog();
			ActiveDbSource = dbd.ActiveSourceInd;
		}

		private void mSqlCreateDb_Click(object sender, System.EventArgs e)
		{
			DbSource source = DbSources[ActiveDbSource];
			Exception ex = source.OpenConnection();
			if(ex != null)
				MessageBox.Show(this, ex.Message, "Unable to proceed.");
			else
			{
				source.OpenConnection();
				CreateBinaryMasksAndDatabase(source);
				source.Connection.Close();
			}
		}

		private void mDbCom_Click(object sender, System.EventArgs e)
		{
		}

		/// <summary>
		/// Generates the script for creating the Pod database.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void mSqlCreateScript_Click(object sender, System.EventArgs e)
		{
			ImageDbTable im = new ImageDbTable();
			ParsedObjectDbTable po = new ParsedObjectDbTable();
			PolygonDbTable poly = new PolygonDbTable();
			string output = "Drop Database Pod If Exists;"
				+ "\nCreate Database Pod;"
				+ "\nUse Pod;"
				+"\n\nCreate Table "+im.SqlCreateTableString
				+"\n\nCreate Table "+po.SqlCreateTableString
				+"\n\nCreate Table "+poly.SqlCreateTableString;
			FormRtb rtb = new FormRtb(output);
			rtb.Activate();
			rtb.Show();
		}

		#endregion
		#region Pb and FormParse Key, Mouse, Paint, Resize Event Handlers
		private void Pb_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
		{
			if(ProjectLoaded)
			{
				if(mNearNeighbor.Checked)
					e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
				else
					e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear;

				RectangleF imgRect = PbToImgRect(e.ClipRectangle);
				e.Graphics.DrawImage(Bmp, e.ClipRectangle,
					imgRect.Left,imgRect.Top,imgRect.Width,imgRect.Height,GraphicsUnit.Pixel);
				if(this.bViewAll.ImageIndex==1)
				{
					if(this.bViewActiveCircle.ImageIndex==1)
					{
						for(int i=0; i<Opd.Circles.Length; i++)
						{
                            if(Opd.Circles[i].Display)
                            {
                                RectangleF circleRect = ImgToPbRectF(Opd.Circles[i].BoundingRectF);
                                e.Graphics.DrawEllipse(CirclePen,circleRect);
                            }
						}
					}
					if(this.bViewActiveCat.ImageIndex > 1)	//	View inactive polygons of active object
					{
						e.Graphics.DrawImage(this.BmpCurrentObj, e.ClipRectangle,
							imgRect.Left,imgRect.Top,imgRect.Width,imgRect.Height,GraphicsUnit.Pixel);
					}
					if(this.bViewActiveCat.ImageIndex > 0)	//	View inactive objects of active category
					{
						e.Graphics.DrawImage(this.BmpOtherObj, e.ClipRectangle,
							imgRect.Left,imgRect.Top,imgRect.Width,imgRect.Height,GraphicsUnit.Pixel);
					}
					if(this.bViewInactiveCat.ImageIndex==1)
					{
						e.Graphics.DrawImage(this.BmpNonObj, e.ClipRectangle,
							imgRect.Left,imgRect.Top,imgRect.Width,imgRect.Height,GraphicsUnit.Pixel);
					}
					if(CurrentTool==ToolType.Polygon || CurrentTool==ToolType.Contour)
						Ptool.OnPaint(sender, e);
					//	View X-junctions
					if(this.bViewXjunc.ImageIndex==2)
					{
						DrawXjuncs(sender, e, Opd.ActiveCategory, true);
					}
					else if(this.bViewXjunc.ImageIndex==1)
					{
						DrawXjuncs(sender, e, Opd.ActivePoly, true);
					}
					//	View T-junctions
					if(this.bViewTjunc.ImageIndex==2)
					{
						DrawJuncs(sender, e, Opd.ActiveCategory, true);
					}
					else if(this.bViewTjunc.ImageIndex==1)
					{
						DrawJuncs(sender, e, Opd.ActivePoly, true);
					}
				}
				if(this.RibbonArrow!=null)
					RibbonArrow.Paint(sender, e);
			}
		}
		public static double XJ_HALFLENGTH = 15.0;
		public void DrawXjuncs(object sender, System.Windows.Forms.PaintEventArgs e, object obj, bool doRecursion)
		{
			if(obj != null)
			{
				int i;
				if(obj.GetType()==typeof(CategoryNode))
				{
					CategoryNode cn = (CategoryNode)obj;
					for(i=0; i<cn.Objects.Count; i++)
						DrawXjuncs(sender, e, cn.Objects[i], doRecursion);
					if(doRecursion)
					{
						for(i=0; i<cn.Sub.Count; i++)
							DrawXjuncs(sender, e, cn.Sub[i], true);
					}
				}
				else if(obj.GetType()==typeof(ParsedObject))
				{
					ParsedObject po = (ParsedObject)obj;
					for(i=0; i<po.Polygons.Count; i++)
						DrawXjuncs(sender, e, po.Polygons[i], doRecursion);
				}
				else if(obj.GetType()==typeof(PolygonF))
				{
					PolygonF poly = (PolygonF)obj;
					Rectangle rect = this.ImgToPbRect( poly.GetBoundingRectF(0.0f) );
					bool contained = e.ClipRectangle.Contains(rect);
					if(e.ClipRectangle.IntersectsWith(rect) || contained)
					{
						if( poly.XjunctionCache==null )
							poly.XjunctionCache=poly.Xjunctions;
						Xjunction[] xja;
						Xjunction xj;
						int n=poly.XjunctionCache.GetLength(0);
						int j,k;
						PointF pf;
						float dx, dy;
						for(i=0; i<n; i++)
						{
							for(j=i; j<n; j++)
							{
								xja = poly.XjunctionCache[i,j];
								if(xja!=null)
								{
									for(k=0; k<xja.Length; k++)
									{
										xj = xja[k];
										pf = ImgToPb(xj.Location);
										if( contained || e.ClipRectangle.Contains( new Point( (int)(pf.X+0.5f), (int)(pf.Y+0.5f) ) ) )
										{
											dx = (float)(xj.Cos1 * FormParse.XJ_HALFLENGTH);
											dy = (float)(xj.Sin1 * FormParse.XJ_HALFLENGTH);
											e.Graphics.DrawLine( Ptool.PenXjunc, pf.X-dx, pf.Y-dy, pf.X+dx, pf.Y+dy );
											dx = (float)(xj.Cos2 * FormParse.XJ_HALFLENGTH);
											dy = (float)(xj.Sin2 * FormParse.XJ_HALFLENGTH);
											e.Graphics.DrawLine( Ptool.PenXjunc, pf.X-dx, pf.Y-dy, pf.X+dx, pf.Y+dy );
										}
									}
								}
							}
						}
					}
				}
			}
		}
		public void DrawJuncs(object sender, System.Windows.Forms.PaintEventArgs e, object obj, bool doRecursion)
		{
			if(obj != null)
			{
				int i;
				if(obj.GetType()==typeof(CategoryNode))
				{
					CategoryNode cn = (CategoryNode)obj;
					for(i=0; i<cn.Objects.Count; i++)
						DrawJuncs(sender, e, cn.Objects[i], doRecursion);
					if(doRecursion)
					{
						for(i=0; i<cn.Sub.Count; i++)
							DrawJuncs(sender, e, cn.Sub[i], true);
					}
				}
				else if(obj.GetType()==typeof(ParsedObject))
				{
					ParsedObject po = (ParsedObject)obj;
					for(i=0; i<po.Polygons.Count; i++)
						DrawJuncs(sender, e, po.Polygons[i], doRecursion);
				}
				else if(obj.GetType()==typeof(PolygonF) || obj.GetType()==typeof(ContourF))
				{
					PathF path = (PathF)obj;
					Rectangle rect = this.ImgToPbRect( path.GetBoundingRectF(0.0f) );
					bool contained = e.ClipRectangle.Contains(rect);
					if(e.ClipRectangle.IntersectsWith(rect) || contained)
					{
						if( path.JunctionFcache==null )
							path.JunctionFcache=path.JunctionFs;
						JunctionF[] juns = path.JunctionFcache;
						JunctionF jun;
						if( juns!=null && juns.Length>0 )
						{
							int k, l;
							float dx, dy;
							PointF pf;
							for(k=0; k<juns.Length; k++)
							{
								jun = juns[k];
								if(jun.Targets!=null)
								{
									pf = ImgToPb(jun.Center);
									for(l=0; l<jun.Targets.Length; l++)
									{
										dx = (float)(jun.Cos[l] * FormParse.XJ_HALFLENGTH);
										dy = (float)(jun.Sin[l] * FormParse.XJ_HALFLENGTH);
										e.Graphics.DrawLine( Ptool.PenTjunc, pf.X, pf.Y, pf.X+dx, pf.Y+dy );
									}
								}
							}
						}
						if( path.GetType()==typeof(PolygonF) )
						{
							PolygonF poly = (PolygonF)path;
							for(i=0; i<poly.Contours.Count; i++)
								DrawJuncs(sender, e, poly.Contours[i], doRecursion);
						}
					}
				}
			}
		}
		private void Pb_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			if(this.ContainsFocus && this.ProjectLoaded)
			{
				if(!Pb.Focused)
					Pb.Focus();
				RemoveRibbonArrow();
				if(e.Button==MouseButtons.Right)		//	Image is being panned.
				{
					if(Ptool.CtrlKeyIsDown)
					{
                        Circle c = CurrentSelection.Roi;
						if(c != null && c.Display)
						{
							c.Center.X = PbToImgX(e.X);
							c.Center.Y = PbToImgY(e.Y);
						}
					}
					else
					{
						float dx = ImgZoomFlow.X - PbToImgX(e.X);
						float dy = ImgZoomFlow.Y - PbToImgY(e.Y);
						ImgRect = new RectangleF(ImgRect.Left+dx, ImgRect.Top+dy, ImgRect.Width, ImgRect.Height);
						ImgRectChangeCt++;
					}
					
					Pb.Invalidate();
				}

				if(CurrentTool==ToolType.Polygon || CurrentTool==ToolType.Contour)
					Ptool.OnMouseMove(sender, e);
				RefreshStatusBar(sender, e);
			}
		}
		public void RefreshStatusBar(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			//string distStr = "";
			CategoryNode cn = Opd.ActiveCategory;
			string selname = cn.Name;
			ParsedObject od = Opd.ActiveObject;
			if(od != null)
				selname = selname + "/" + od.Name;
			PolygonF pf = Opd.ActivePoly;
			if(pf != null)
			{
                selname = selname + "/Poly_" + Convert.ToString(od.Polygons.IndexOf(pf))
                + "_" + od.Polygons.Count;
				if(Ptool.DrawPts[0])
					selname = selname + "/Vertex_" +  Convert.ToString(pf.IndexOf(Ptool.ImgLeg[0]));
				//distStr = Convert.ToString((int)Math.Round( pf.DistanceToLeg(new PointF(PbToImgX((float)e.X), PbToImgY((float)e.Y)))));
			}
			string linkTxt = "";
			if(Ptool.LinkMode)
			{
				linkTxt = "  [Link "+Convert.ToString(Ptool.LinkStage)+"]";
				if(Ptool.Glider != null)
				{
					linkTxt = linkTxt + "  [Glide " + Convert.ToString(Ptool.Glider.Count) + "]";
				}
			}
			string circleTxt = "";
			if(Opd.Circles.Length > 0)
			{
				if(Opd.ActiveCircleInd>=0 && Opd.ActiveCircleInd<Opd.Circles.Length)
				{
					if(Opd.Circles[Opd.ActiveCircleInd].Display)
						circleTxt = "{" + Opd.Circles[Opd.ActiveCircleInd].ToString() + "} ";
					else
						circleTxt = "{Hidden}";
				}
			}
			statusBar1.Text = circleTxt + selname + " " +
				"["+Convert.ToString((int)PbToImgX((float)e.X))+","+Convert.ToString((int)PbToImgY((float)e.Y))+"]"
				+linkTxt;
		}
		private void Pb_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
		{
            CheckUndoStack();
			if(this.ProjectLoaded)
			{
				if(e.Button==MouseButtons.Right)		//	Drag Image
				{
					ImgZoomFlow.X = PbToImgX(e.X);
					ImgZoomFlow.Y = PbToImgY(e.Y);
					Cursor.Current = Cursors.Hand;
					ShowCursor();
				}
				
				if( (CurrentTool==ToolType.Polygon || CurrentTool==ToolType.Contour) && Ptool!=null )
					Ptool.OnMouseDown(sender, e);
			}
		}
		private void Pb_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			if(ProjectLoaded && Ptool!=null && (CurrentTool==ToolType.Polygon || CurrentTool==ToolType.Contour) )
				Ptool.OnMouseUp(sender, e);
		}
		private void Pb_MouseLeave(object sender, System.EventArgs e)
		{
			Cursor.Current = Cursors.Default;
		}
		private void Pb_MouseEnter(object sender, System.EventArgs e)
		{
			this.Activate();
			if(ProjectLoaded && Ptool!=null && (CurrentTool==ToolType.Polygon || CurrentTool==ToolType.Contour))
				Ptool.OnPb_MouseEnter(sender, e);
		}
		private void Pb_SizeChanged(object sender, System.EventArgs e)
		{
			if(ProjectLoaded && Pb.Width>0 && Pb.Height>0)
			{
				Size newSize = new Size(Pb.Width, Pb.Height);
				double whOld = (double)PbSize.Width/(double)PbSize.Height;
				double whNew = (double)newSize.Width/(double)newSize.Height;
				double newOld = whNew/whOld;
				double wNew = ImgRect.Width*Math.Sqrt(newOld);
				double hNew = ImgRect.Height/Math.Sqrt(newOld);
				float xc = ImgRect.Width/2.0f+ImgRect.Left;
				float yc = ImgRect.Height/2.0f+ImgRect.Top;
				ImgRect = new RectangleF(xc-(float)wNew/2.0f, yc-(float)hNew/2.0f, (float)wNew, (float)hNew);
				PbSize = newSize;
			
				if( (CurrentTool==ToolType.Polygon || CurrentTool==ToolType.Contour) && Ptool!=null )
					Ptool.OnPb_SizeChanged(sender, e);

				ImgRectChangeCt++;

				Pb.Invalidate();
			}
		}
		public void FormParse_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
		{
            CheckUndoStack();
			//	Edge viewing
			if(!e.Control && !e.Shift)
			{
				if( e.KeyCode==Keys.Space )
					bViewButton_MouseUp( this.bViewAll, null );
			}
			//	Other viewing
			if(ProjectLoaded)
			{
				if(!e.Control && !e.Shift)
				{
					if(e.KeyCode==System.Windows.Forms.Keys.Space)
						this.bViewAll.PerformClick();
					else if(e.KeyCode==System.Windows.Forms.Keys.Left)
						this.mJumpLastPath.PerformClick();
					else if(e.KeyCode==System.Windows.Forms.Keys.Right)
						this.mJumpNextPath.PerformClick();
					else if(e.KeyCode==System.Windows.Forms.Keys.Up)
						this.mSeriesBackward.PerformClick();
					else if(e.KeyCode==System.Windows.Forms.Keys.Down)
						this.mSeriesForward.PerformClick();
					else if(	FormCat!=null && !FormCat.IsDisposed
							||	e.KeyCode==Keys.D0 || e.KeyCode==Keys.NumPad0
							||	e.KeyCode==Keys.D1 || e.KeyCode==Keys.NumPad1
							||	e.KeyCode==Keys.D2 || e.KeyCode==Keys.NumPad2
							||	e.KeyCode==Keys.D3 || e.KeyCode==Keys.NumPad3
							||	e.KeyCode==Keys.D4 || e.KeyCode==Keys.NumPad4
							||	e.KeyCode==Keys.D5 || e.KeyCode==Keys.NumPad5
							||	e.KeyCode==Keys.D6 || e.KeyCode==Keys.NumPad6
							||	e.KeyCode==Keys.D7 || e.KeyCode==Keys.NumPad7
							||	e.KeyCode==Keys.D8 || e.KeyCode==Keys.NumPad8
							||	e.KeyCode==Keys.D9 || e.KeyCode==Keys.NumPad9 )
					{
						FormCat.FormCategorize_KeyUp(sender, e);
					}
				}
                if( Ptool!=null )
					Ptool.OnKeyUp(sender, e);
			}
		}
		public void FormParse_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
		{
			if(Ptool!=null &&
                (CurrentTool==ToolType.Polygon
                    || CurrentTool==ToolType.Contour
                    || (CurrentTool==ToolType.Circle &&
                        e.KeyCode==Keys.ControlKey)
                )
               )
				Ptool.OnKeyDown(sender, e);
		}
		private void FormParse_MouseWheel(object sender, MouseEventArgs e)
		{
			if(this.ContainsFocus && ProjectLoaded)
			{
				//	Is cursor in range of Pb?
				Point pt = Pb.PointToClient(Cursor.Position);
				if(pt.X>0&&pt.Y>0 && pt.X<Pb.Width && pt.Y<Pb.Height)
				{
					if(this.Ptool.CtrlKeyIsDown)
					{
                        if(CurrentTool==ToolType.Circle && CurrentSelection.Roi!=null && CurrentSelection.Roi.Display)
                        {
                            float radius = CurrentSelection.Roi.Radius;
                            if((e.Delta<0.0 && radius > 5.0) || e.Delta>0.0)
                            {
                                float div = (float)Math.Floor((double)radius/5.0);
                                div += e.Delta/120.0f;
                                CurrentSelection.Roi.Radius = div*5.0f;
                                RefreshStatusBar(sender,e);
                                Pb.Invalidate();
                            }
                        }
					}
					else
					{
						if((e.Delta<0.0 && Math.Min(ImgRect.Width/(float)Pb.Width,ImgRect.Height/(float)Pb.Height)<10.0) || e.Delta>=0.0)
						{
							//	ImgZooming
							float ptx, pty, fz, dl, dt;
							//	Screen location of cursor (could have just used Cursor.Location)
							Point p = this.PointToScreen(new Point(e.X,e.Y));
							//	Compute where the cursor is in image coordinates.
							p = Pb.PointToClient(new Point(p.X, p.Y));
							ptx = PbToImgX((float)p.X);
							pty = PbToImgY((float)p.Y);
							//	Compute the factor change in zoom.
							fz = 1.0f-(float)e.Delta/120.0f/20.0f;
							//	Compute the change in left and top points.
							dl=-(ptx-ImgRect.Left)*fz;
							dt=-(pty-ImgRect.Top)*fz;
							//	Generate the new rectangle
							ImgRect = new RectangleF(ptx+dl, pty+dt, ImgRect.Width*fz, ImgRect.Height*fz);
					
							if(CurrentTool==ToolType.Polygon || CurrentTool==ToolType.Contour)
								Ptool.OnMouseWheel(sender, e);
							ImgRectChangeCt++;
					
							//	Invalidate the control.
							Pb.Invalidate();
						}
					}
				}
				else
				{
					//	Is cursor in range of PbRibbon?
					pt = PbRibbon.PointToClient(Cursor.Position);
					if(pt.X>0&&pt.Y>0 && pt.X<PbRibbon.Width && pt.Y<PbRibbon.Height)
						PbRibbon.PbViewer_MouseWheel(sender, e);
				}
			}
		}
		#endregion
		#region View menu options for "Show ..."
        /*
		private void mShowClaimedFilters_Click(object sender, System.EventArgs e)
		{
			if(ProjectLoaded)
			{
				this.mShowClaimedFilters.Checked = !this.mShowClaimedFilters.Checked;
				Pb.Invalidate();
			}
		}
		private void mShowUnclaimedFilters_Click(object sender, System.EventArgs e)
		{
			if(ProjectLoaded)
			{
				this.mShowUnclaimedFilters.Checked = !this.mShowUnclaimedFilters.Checked;
				Pb.Invalidate();
			}
		}
		private void mShowSubThreshFilters_Click(object sender, System.EventArgs e)
		{
			if(ProjectLoaded)
			{
				this.mShowSubThreshFilters.Checked = !this.mShowSubThreshFilters.Checked;
				Pb.Invalidate();
			}
		}
        private void mShowPeriods_Click(object sender, System.EventArgs e)
		{
			this.mShowPeriods.Checked = !this.mShowPeriods.Checked;
			Pb.Invalidate();
		}
        */
        #endregion
        #region Color Menu
        private void mOpsColsCurObj_Click(object sender, System.EventArgs e)
		{
			ColorDialog cd = new ColorDialog();
			cd.AllowFullOpen = true;
			cd.AnyColor=true;
			cd.SolidColorOnly = false;
			cd.Color = Opd.ObjCurrColor;
			if (cd.ShowDialog() == DialogResult.OK)
			{
				Opd.ObjCurrColor =  Color.FromArgb(Opd.ObjCurrColor.A, cd.Color.R, cd.Color.G, cd.Color.B);
				for(int i=0; i<BmpCurrentObj.Width; i++)
					for(int j=0; j<BmpCurrentObj.Height; j++)
						if(BmpCurrentObj.GetPixel(i,j).A!=0)
							BmpCurrentObj.SetPixel(i,j,Opd.ObjCurrColor);
				Pb.Invalidate();
			}
		}

		private void mOpsColsOtherObj_Click(object sender, System.EventArgs e)
		{
			ColorDialog cd = new ColorDialog();
			cd.AllowFullOpen = true;
			cd.AnyColor=true;
			cd.SolidColorOnly = false;
			cd.Color = Opd.ObjOtherColor;
			if (cd.ShowDialog() == DialogResult.OK)
			{
				Opd.ObjOtherColor =  Color.FromArgb(Opd.ObjOtherColor.A, cd.Color.R, cd.Color.G, cd.Color.B);
				for(int i=0; i<BmpOtherObj.Width; i++)
					for(int j=0; j<BmpOtherObj.Height; j++)
						if(BmpOtherObj.GetPixel(i,j).A!=0)
							BmpOtherObj.SetPixel(i,j,Opd.ObjOtherColor);
				Pb.Invalidate();
			}
		}

		private void mOpsColsNonObj_Click(object sender, System.EventArgs e)
		{
			ColorDialog cd = new ColorDialog();
			cd.AllowFullOpen = true;
			cd.AnyColor=true;
			cd.SolidColorOnly = false;
			cd.Color = Opd.ObjNonColor;
			if (cd.ShowDialog() == DialogResult.OK)
			{
				Opd.ObjNonColor =  Color.FromArgb(Opd.ObjNonColor.A, cd.Color.R, cd.Color.G, cd.Color.B);
				for(int i=0; i<BmpNonObj.Width; i++)
					for(int j=0; j<BmpNonObj.Height; j++)
						if(BmpNonObj.GetPixel(i,j).A!=0)
							BmpNonObj.SetPixel(i,j,Opd.ObjNonColor);
				Pb.Invalidate();
			}
		}

		private void mOpsColsPolyLine_Click(object sender, System.EventArgs e)
		{
			ColorDialog cd = new ColorDialog();
			cd.AllowFullOpen = true;
			cd.AnyColor=true;
			cd.SolidColorOnly = false;
			cd.Color = Opd.PolyLineColor;
			if (cd.ShowDialog() == DialogResult.OK)
			{
				Opd.PolyLineColor = Color.FromArgb(Opd.PolyLineColor.A, cd.Color.R, cd.Color.G, cd.Color.B);
				Ptool.InitPens();
				Pb.Invalidate();
			}
		}

		private void mOpsAlphaPolyLine_Click(object sender, System.EventArgs e)
		{
			AlphaDialog ad = new AlphaDialog(Opd.PolyLineColor.A);
			if(ad.ShowDialog() == DialogResult.OK)
			{
				Opd.PolyLineColor = Color.FromArgb(ad.AlphaLevel,
					Opd.PolyLineColor.R, Opd.PolyLineColor.G, Opd.PolyLineColor.B);
				Pb.Invalidate();
			}
		}

		private void mOpsAlphaCurObj_Click(object sender, System.EventArgs e)
		{
			AlphaDialog ad = new AlphaDialog(Opd.ObjCurrColor.A);
			if(ad.ShowDialog() == DialogResult.OK)
			{
				Opd.ObjCurrColor = Color.FromArgb(ad.AlphaLevel, Opd.ObjCurrColor.R, Opd.ObjCurrColor.G, Opd.ObjCurrColor.B);
				for(int i=0; i<this.BmpCurrentObj.Width; i++)
					for(int j=0; j<BmpCurrentObj.Height; j++)
						if(BmpCurrentObj.GetPixel(i,j).A!=0)
							BmpCurrentObj.SetPixel(i,j,Opd.ObjCurrColor);
				Pb.Invalidate();
			}
		}

		private void mOpsAlphaOtherObj_Click(object sender, System.EventArgs e)
		{
			AlphaDialog ad = new AlphaDialog(Opd.ObjOtherColor.A);
			if(ad.ShowDialog() == DialogResult.OK)
			{
				Opd.ObjOtherColor = Color.FromArgb(ad.AlphaLevel, Opd.ObjOtherColor.R, Opd.ObjOtherColor.G, Opd.ObjOtherColor.B);
				for(int i=0; i<BmpOtherObj.Width; i++)
					for(int j=0; j<BmpOtherObj.Height; j++)
						if(BmpOtherObj.GetPixel(i,j).A!=0)
							BmpOtherObj.SetPixel(i,j,Opd.ObjOtherColor);
				Pb.Invalidate();
			}
		}

		private void mOpsAlphaNonObj_Click(object sender, System.EventArgs e)
		{
			AlphaDialog ad = new AlphaDialog(Opd.ObjNonColor.A);
			if(ad.ShowDialog() == DialogResult.OK)
			{
				Opd.ObjNonColor = Color.FromArgb(ad.AlphaLevel, Opd.ObjNonColor.R, Opd.ObjNonColor.G, Opd.ObjNonColor.B);
				for(int i=0; i<BmpNonObj.Width; i++)
					for(int j=0; j<BmpNonObj.Height; j++)
						if(BmpNonObj.GetPixel(i,j).A!=0)
							BmpNonObj.SetPixel(i,j,Opd.ObjNonColor);
				Pb.Invalidate();
			}
		}
		
		#endregion
		#region Ribbon Stuff
		private void splitRightHor_DoubleClick(object sender, System.EventArgs e)
		{
			PbRibbon.Height=0;
			UpdatePbSize();
		}
		private void splitRightHor_SplitterMoved(object sender, System.Windows.Forms.SplitterEventArgs e)
		{
			UpdatePbSize();
		}
		private void PbRibbon_ImgRectChanged(object sender, System.EventArgs e)
		{
			ActiveSurfaces_UpdateView();
		}
		public void ActiveSurfaces_UpdateView()
		{
			if(ActiveSurfaces!=null && ActiveSurfaces.Painter!=null && PbRibbon.Height>0 && PbRibbon.Width>0)
			{
				//	Send the viewer information to the ActiveSurfaces
				ActiveSurfaces.Painter.ViewerRect
					= PbRibbon.ImgToViewerRectF(ActiveSurfaces.Painter.NaturalRect);
			}
		}
		private void PbRibbon_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			Cursor.Current = Cursors.Cross;
			if(!PbRibbon.Focused)
				PbRibbon.Focus();
			if(ActiveSurfaces!=null)
			{
				PointF imgArrow = ActiveSurfaces.GetImgCoordinates( PbRibbon.PointToClient(Cursor.Position) );
				if(imgArrow==PointF.Empty)
					RemoveRibbonArrow();
				else
					MoveRibbonArrow( ImgToPb(imgArrow) );
			}
		}
		private void PbRibbon_MouseLeave(object sender, System.EventArgs e)
		{
			RemoveRibbonArrow();
		}
		public SurfaceBoundList ActiveSurfaces;
		public void NewActiveSurfaces()
		{
			if(Opd!=null)
			{
				ParsedObject po = Opd.ActiveObject;
				if(po!=null)
				{
					//	Initiate the surface list.
					ActiveSurfaces = new SurfaceBoundList(po, 1.0f);
					//	Make sure there are core pixels loaded
					if(this.CorePixels==null)
						this.LoadCorePixels();
					float rgbFac = Opd.PixelFactor;
					if(rgbFac <= 0.0f || float.IsNaN(rgbFac) )
						rgbFac = 1000.0f;
					//	Calculate the ribbons
					ActiveSurfaces.CalcRibbons(
						this.CorePixels, rgbFac,
						Util.LinSpace(-10.0f, 10.0f, 1.0f), 2.0f,
                        new BmgNet.ColorSpace[] {BmgNet.ColorSpace.LogLmsOpp}, null, 0, null);
					ActiveSurfaces.InitPainting(this.PbRibbon.Size, this.Bmp);
					//	Init Zoom
					PbRibbon.InitZoom(ActiveSurfaces.Painter.NaturalRect);
					//	Offset to view text (text was defined with negative coordinates)
					RectangleF rv = PbRibbon.ImgRect;
					rv.Offset(-80.0f*ActiveSurfaces.Painter.NaturalRect.Width/(float)PbRibbon.Width, 0.0f);
					PbRibbon.ImgRect=rv;
					//	Set the viewer
					ActiveSurfaces_UpdateView();
				}
			}
			//	Invalidate
			PbRibbon.Invalidate();
		}
		private void PbRibbon_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			if(e.Button==MouseButtons.Left)
				NewActiveSurfaces();
		}
		private void PbRibbon_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
		{
			if(ActiveSurfaces!=null && ActiveSurfaces.Painter!=null)
				ActiveSurfaces.Painter.Paint(sender, e);
		}
		private void PbRibbon_MouseEnter(object sender, System.EventArgs e)
		{
			Cursor.Current = Cursors.Cross;
		}
		private void mCopyRibbons_Click(object sender, System.EventArgs e)
		{
			if(ActiveSurfaces!=null && ActiveSurfaces.Painter!=null)
			{
				RectangleF oldView = ActiveSurfaces.Painter.ViewerRect;
				ActiveSurfaces.Painter.ViewerRect = ActiveSurfaces.Painter.NaturalRect;
				Bitmap bmp = new Bitmap(
					(int)ActiveSurfaces.Painter.ViewerRect.Width+60,
					(int)ActiveSurfaces.Painter.ViewerRect.Height );
				ActiveSurfaces.Painter.Paint(bmp,
					new PaintEventArgs(Graphics.FromImage(bmp),
					new Rectangle(60,0,bmp.Width,bmp.Height)));
				Clipboard.SetDataObject(bmp);
				ActiveSurfaces.Painter.ViewerRect = oldView;
			}
		}
		public Arrow RibbonArrow=null;
		public void MoveRibbonArrow(PointF destination)
		{
			if(RibbonArrow!=null)
			{
				Pb.Invalidate(RibbonArrow.BoundingRect);
				RibbonArrow = new Arrow(destination, RibbonArrow.Radians, RibbonArrow.Length, RibbonArrow.Width, RibbonArrow.FillBrush.Color);
			}
			else
				RibbonArrow = new Arrow(destination, 0.6*Math.PI, 50.0, 15.0, Color.Red);
			Pb.Invalidate(RibbonArrow.BoundingRect);
		}
		public void MoveRibbonArrow(PointF destination, double orientationRadians)
		{
			if(RibbonArrow!=null)
			{
				Pb.Invalidate(RibbonArrow.BoundingRect);
				RibbonArrow = new Arrow(destination, orientationRadians, RibbonArrow.Length, RibbonArrow.Width, RibbonArrow.FillBrush.Color);
			}
			else
				RibbonArrow = new Arrow(destination, orientationRadians, 50.0, 15.0, Color.Red);
			Pb.Invalidate(RibbonArrow.BoundingRect);
		}
		public void RemoveRibbonArrow()
		{
			if(RibbonArrow!=null)
				Pb.Invalidate(RibbonArrow.BoundingRect);
			RibbonArrow=null;
		}
		#endregion
        #region Batch Stuff
        private void mBatchExportBasicHists(object sender, System.EventArgs e)
        {
            Cursor = Cursors.WaitCursor;

            BmgNet.ColorSpace[] spaces= new BmgNet.ColorSpace[] { ColorSpace.LogLmsOpp };
            if(OfdBatch==null)
                OfdBatch = new OpenFileDialog();
            OfdBatch.Multiselect = true;
            OfdBatch.Filter = "Object Parser Files | *.ObjParser";
            if(OfdBatch.ShowDialog()==DialogResult.OK)
            {
                string[] fnames = OfdBatch.FileNames;
                if(fnames != null)
                {
                    EngMATAccess matlab=null;
                    bool proceed = true;
                    try
                    {
                        matlab = ObjectParserData.Matlab;
                    }
                    catch
                    {
                        proceed = false;
                        MessageBox.Show(this,"Matlab could not be started.");
                    }

                    if(proceed && !matlab.Active)
                    {
                        proceed = false;
                        MessageBox.Show(this,"Matlab is not active.");
                    }

                    if(proceed)
                    {
                        ArrayList areaPoly=new ArrayList();
                        ArrayList areaObj=new ArrayList();
                        ArrayList areaPolyObs=new ArrayList();
                        ArrayList nPolys=new ArrayList();
                        int i,j,ct,errmsg;
                        for(ct=0;ct<fnames.Length;ct++)
                        {
                            ObjectParserData opd = ObjectParserData.Deserialize(fnames[ct], this, SerializationType.Binary);
                            Ushort3 corePix = Ushort3.FromPng16(opd.Imagename,out errmsg);
                            if(corePix==null)
                                MessageBox.Show("Break analysis.  Image did not load.  Fix data file.");
                            CategoryNode cn = opd.RootCategory.GetSubRecursive("Leaves");
                            if(cn==null)
                                MessageBox.Show("No category named Leaves.  Break analysis.  Fix data file.");

                            ParsedObject po;
                            for(i=0;i<cn.Objects.Count;i++)
                            {
                                po = cn.Objects[i];
                                if(po.CatData.Quality==2)
                                {
                                    nPolys.Add((double)po.Polygons.Count);
                                    areaObj.Add((double)po.Area);
                                    for(j=0; j<po.Polygons.Count; j++)
                                    {
                                        areaPoly.Add((double)po.Polygons[j].Pix.NumPts);
                                        areaPolyObs.Add((double)po.Polygons[j].Pix.NumPts / (double)po.Area);
                                    }
                                }
                            }
                        }
                        matlab.EvaluateAsString("basic=[];");

                        matlab.SetMatrix("temp", (double[])areaPoly.ToArray(typeof(double)));
                        matlab.EvaluateAsString("basic.PolygonAreas=temp");

                        matlab.SetMatrix("temp",(double[])areaObj.ToArray(typeof(double)));
                        matlab.EvaluateAsString("basic.ObjectAreas=temp");

                        matlab.SetMatrix("temp",(double[])areaPolyObs.ToArray(typeof(double)));
                        matlab.EvaluateAsString("basic.PolygonAreasObs=temp");

                        matlab.SetMatrix("temp",(double[])nPolys.ToArray(typeof(double)));
                        matlab.EvaluateAsString("basic.Npolys=temp");

                        matlab.EvaluateAsString("save e:/basic basic;");
                    }
                }
            }
        }
        private void mBatchExportRoiPatches_Click(object sender,System.EventArgs e)
        {
            Cursor = Cursors.WaitCursor;

            BmgNet.ColorSpace[] spaces= new BmgNet.ColorSpace[] { ColorSpace.LogLmsOpp };
            if(OfdBatch==null)
                OfdBatch = new OpenFileDialog();
            OfdBatch.Multiselect = true;
            OfdBatch.Filter = "Object Parser Files | *.ObjParser";
            if(OfdBatch.ShowDialog()==DialogResult.OK)
            {
                string[] fnames = OfdBatch.FileNames;
                if(fnames != null)
                {
                    EngMATAccess matlab=null;
                    bool proceed = true;
                    try
                    {
                        matlab = ObjectParserData.Matlab;
                    }
                    catch
                    {
                        proceed = false;
                        MessageBox.Show(this,"Matlab could not be started.");
                    }

                    if(proceed && !matlab.Active)
                    {
                        proceed = false;
                        MessageBox.Show(this,"Matlab is not active.");
                    }

                    if(proceed)
                    {
                        int i,j,k,ct,errmsg,iy, jx, ncir, nciry;
                        //  Apply the coordinate offset on odd numbered rows
                        Point pt;
                        float limsq;
                        List<Circle> cirs = new List<Circle>();
                        List<double[]> means = new List<double[]>();
                        Circle cir;
                        double[] mean;
                        double[,] cov;
                        int nValid, nInvalid;
                        int ctRoi = 0;
                        ArrayList data = new ArrayList();
                        //  For each parsed object, get accrued PixelTagger
                        List<PixelTagger> ptags = new List<PixelTagger>();
                        PixelTagger pix;
                        ParsedObject po;
                        matlab.EvaluateAsString("Roi = [];");

                        for(ct=0;ct<fnames.Length;ct++)
                        {
                            ObjectParserData opd = ObjectParserData.Deserialize(fnames[ct], this, SerializationType.Binary);
                            Ushort3 corePix = Ushort3.FromPng16(opd.Imagename,out errmsg);
                            if(corePix==null)
                                MessageBox.Show("Break analysis.  Image did not load.  Fix data file.");
                            CategoryNode cn = opd.RootCategory.GetSubRecursive("Leaves");
                            if(cn==null)
                                MessageBox.Show("No category named Leaves.  Break analysis.  Fix data file.");
                            
                            //  For each circle, sample random pts inside
                            for(i=0; i<opd.Circles.Length; i++)
                            {
                                //  The patch diameter
                                int diameter = (int)(opd.Circles[i].Radius/10.0f);
                                float off = (float)((double)diameter/Math.Sqrt(2));
                                if( diameter > 5 )
                                {
                                    //  For each object and ROI combination
                                    ptags.Clear();
                                    for(j=0;j<cn.Objects.Count;j++)
                                    {
                                        po = cn.Objects[j];
                                        if(po.CatData.Quality==2)
                                        {
                                            pix = po.Polygons[0].Pix.Clone;
                                            for(k=1;k<po.Polygons.Count;k++)
                                                pix.AddPix(po.Polygons[k].Pix);
                                            pix.Union(opd.Circles[i]);
                                            if(pix.NumPts>diameter)
                                                ptags.Add(pix);
                                        }
                                    }
                                    if( ptags.Count>0 )
                                    {
                                        //  For each patch in the ROI
                                        cirs.Clear();
                                        means.Clear();
                                        //  Compute the squared radius
                                        limsq = opd.Circles[i].Radius-(float)diameter/2.0f;
                                        limsq *= limsq;
                                        //  Sample with subcircles included within this radius
                                        ncir = (int)(opd.Circles[i].Radius/(float)diameter+0.8);
                                        nciry = (int)(1.42f*opd.Circles[i].Radius/(float)diameter+0.8);
                                        //  Here is a circle
                                        for(iy=-nciry; iy<=nciry; iy++)
                                            for(jx=-ncir; jx<=ncir; jx++)
                                            {
                                                pt = new Point( (int)(jx*diameter+(iy%2)*diameter/2.0f+0.5f), (int)((float)iy*off+0.5f) );
                                                //  The circle is contained within the ROI
                                                if( (float)(pt.X*pt.X + pt.Y*pt.Y) < limsq )
                                                {
                                                    pt.X += (int)(0.5f+opd.Circles[i].Center.X);
                                                    pt.Y += (int)(0.5f+opd.Circles[i].Center.Y);
                                                    cir = new Circle(pt, (diameter+1)/2, false);
                                                    cir.CalcStats(corePix, opd.PixelFactor, false, out mean, out cov, out nValid, out nInvalid);
                                                    if( nValid>diameter )
                                                    {
                                                        cirs.Add(cir);
                                                        means.Add(mean);
                                                    }
                                                }
                                            }
                                        if( cirs.Count>1 )
                                        {
                                            ctRoi++;
                                            matlab.EvaluateAsString("roi = struct('Proj', '" + opd.ShortProjname + "');");
                                            matlab.EvaluateAsString("roi.X = " + opd.Circles[i].Center.X.ToString() + ";");
                                            matlab.EvaluateAsString("roi.Y = " + opd.Circles[i].Center.Y.ToString() + ";");
                                            matlab.EvaluateAsString("roi.Rad = " + opd.Circles[i].Radius.ToString() + ";");
                                            matlab.EvaluateAsString("roi.PatchDia = " + diameter.ToString() + ";");
                                            double[,] id = new double[ptags.Count, cirs.Count];
                                            double[,] xyLoc = new double[cirs.Count,2];
                                            double[,] lyr = new double[cirs.Count,3];
                                            double[] dias = new double[ptags.Count];
                                            for(k=0;k<cirs.Count;k++)
                                            {
                                                xyLoc[k,0] = cirs[k].Center.X;
                                                xyLoc[k,1] = cirs[k].Center.Y;
                                                lyr[k,0] = means[k][0];
                                                lyr[k,1] = means[k][1];
                                                lyr[k,2] = means[k][2];
                                                for(j=0;j<ptags.Count;j++) 
                                                    id[j,k] = ptags[j].ProportionOfCircle(cirs[k]);
                                            }
                                            for(j=0;j<ptags.Count;j++) 
                                            {
                                                dias[j] = Math.Sqrt((double)ptags[j].NumPts);
                                            }
                                            matlab.SetMatrix("temp",xyLoc);
                                            matlab.EvaluateAsString("roi.Patches=single(temp);");
                                            matlab.SetMatrix("temp",lyr);
                                            matlab.EvaluateAsString("roi.PatchMeans=single(temp);");
                                            matlab.SetMatrix("temp",dias);
                                            matlab.EvaluateAsString("roi.ObjDia=single(temp);");
                                            matlab.SetMatrix("temp", id);
                                            matlab.EvaluateAsString("roi.Id=single(temp);");
                                            matlab.EvaluateAsString("Roi = [Roi, roi];");
                                        }
                                    }
                                }
                            }
                            corePix.Dispose();
                            System.GC.Collect();
                        }
                        matlab.EvaluateAsString("save e:/RoiData Roi;");
                    }
                }
            }
        }
        private void mBatchExportCircles2_Click(object sender,System.EventArgs e)
        {
            Cursor = Cursors.WaitCursor;

            BmgNet.ColorSpace[] spaces= new BmgNet.ColorSpace[] { ColorSpace.LogLmsOpp };
            if(OfdBatch==null)
                OfdBatch = new OpenFileDialog();
            OfdBatch.Multiselect = true;
            OfdBatch.Filter = "Object Parser Files | *.ObjParser";
            if(OfdBatch.ShowDialog()==DialogResult.OK)
            {
                string[] fnames = OfdBatch.FileNames;
                if(fnames != null)
                {
                    EngMATAccess matlab=null;
                    bool proceed = true;
                    try
                    {
                        matlab = ObjectParserData.Matlab;
                    }
                    catch
                    {
                        proceed = false;
                        MessageBox.Show(this,"Matlab could not be started.");
                    }

                    if(proceed && !matlab.Active)
                    {
                        proceed = false;
                        MessageBox.Show(this,"Matlab is not active.");
                    }

                    if(proceed)
                    {
                        bool doCosWin = true;
                        int nPairs = 10;
                        int i,j,k,ct,errmsg,diameter,sep;
                        double size,sizeFac=0.1;
                        // The spacing between the edges of the circles in units of diameters
                        double[] spacers = new double[] { 0.5,1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5,10.5,11.5 };
                        Circle[] cirs;
                        ArrayList within = new ArrayList();
                        ArrayList across = new ArrayList();
                        int nValid,nInvalid;
                        double[] mean;
                        double[,] cov;
                        int ctAll=0,ctUni=0,ctShad=0;
                        matlab.EvaluateAsString("wGood=0;");
                        matlab.EvaluateAsString("aGood=0;");
                        matlab.EvaluateAsString("all=[];");
                        matlab.EvaluateAsString("all.Leaves=[];");
                        matlab.EvaluateAsString("uni=[];");
                        matlab.EvaluateAsString("uni.Leaves=[];");
                        matlab.EvaluateAsString("shad=[];");
                        matlab.EvaluateAsString("shad.Leaves=[];");

                        for(ct=0;ct<fnames.Length;ct++)
                        {
                            ObjectParserData opd = ObjectParserData.Deserialize(fnames[ct], this, SerializationType.Binary);
                            Ushort3 corePix = Ushort3.FromPng16(opd.Imagename,out errmsg);
                            if(corePix==null)
                                MessageBox.Show("Break analysis.  Image did not load.  Fix data file.");
                            CategoryNode cn = opd.RootCategory.GetSubRecursive("Leaves");
                            if(cn==null)
                                MessageBox.Show("No category named Leaves.  Break analysis.  Fix data file.");

                            ParsedObject po;
                            ContourF con;
                            for(i=0;i<cn.Objects.Count;i++)
                            {
                                po = cn.Objects[i];
                                if(po.CatData.Quality==2)
                                {
                                    size = Math.Sqrt((double)po.Area);
                                    diameter = (int)(sizeFac*size+0.5);
                                    if(diameter > 3)
                                    {
                                        bool hasShadows = false;
                                        bool hasNoShadows = true;
                                        for(j=0;j<po.Polygons.Count;j++)
                                            for(k=0;k<po.Polygons[j].Contours.Count;k++)
                                            {
                                                con = po.Polygons[j].Contours[k];
                                                if(con.CatData.ShadowBorder==3)
                                                    hasShadows=true;
                                                if(con.CatData.ShadowBorder>1)
                                                    hasNoShadows=false;
                                            }

                                        matlab.EvaluateAsString("obj = [];");
                                        matlab.EvaluateAsString("obj.Name='"+ opd.ShortProjname+"/"+po.Name+"';");
                                        matlab.EvaluateAsString("obj.Size=" + size.ToString() + ";");

                                        for(j=0;j<spacers.Length;j++)
                                        {
                                            sep = (int)(0.5+spacers[j]*(double)diameter);

                                            across.Clear();
                                            po.FindPairsAcross(across,nPairs,diameter,sep);
                                            matlab.EvaluateAsString("aGood=aGood+"+across.Count.ToString()+";");
                                            matlab.EvaluateAsString("within=[]; across=[];");
                                            for(k=0;k<across.Count;k++)
                                            {
                                                cirs = (Circle[])across[k];

                                                cirs[0].CalcStats(corePix,opd.PixelFactor,doCosWin,out mean,out cov,out nValid,out nInvalid);
                                                matlab.EvaluateAsString("acir=struct('X', " + 
                                                    cirs[0].Center.X.ToString() + ", 'Y', " + 
                                                    cirs[0].Center.Y.ToString() + ", 'Diameter', " + 
                                                    (cirs[0].Radius*2.0f).ToString() + ", 'Nvalid', " + 
                                                    nValid.ToString() + ", 'Ninvalid', " + 
                                                    nInvalid.ToString() + ");");
                                                matlab.SetMatrix("temp",mean);
                                                matlab.EvaluateAsString("acir.Mean = temp;");
                                                matlab.SetMatrix("temp",cov);
                                                matlab.EvaluateAsString("acir.Cov = temp;");

                                                cirs[1].CalcStats(corePix,opd.PixelFactor,doCosWin,out mean,out cov,out nValid,out nInvalid);
                                                matlab.EvaluateAsString("bcir=struct('X', " + 
                                                    cirs[1].Center.X.ToString() + ", 'Y', " + 
                                                    cirs[1].Center.Y.ToString() + ", 'Diameter', " + 
                                                    (cirs[1].Radius*2.0f).ToString() + ", 'Nvalid', " + 
                                                    nValid.ToString() + ", 'Ninvalid', " + 
                                                    nInvalid.ToString() + ");");
                                                matlab.SetMatrix("temp",mean);
                                                matlab.EvaluateAsString("bcir.Mean = temp;");
                                                matlab.SetMatrix("temp",cov);
                                                matlab.EvaluateAsString("bcir.Cov = temp;");

                                                if(k==0)
                                                {
                                                    matlab.EvaluateAsString("across = struct('Inner', acir, 'Outer', bcir);");
                                                    matlab.EvaluateAsString("across.Separation=" + sep.ToString() + ";");
                                                }
                                                else
                                                {
                                                    matlab.EvaluateAsString("across.Inner(" +(k+1).ToString()+ ")=acir;");
                                                    matlab.EvaluateAsString("across.Outer(" +(k+1).ToString()+ ")=bcir;");
                                                }
                                            }
                                            if(j==0)
                                                matlab.EvaluateAsString("obj.Across=across;");
                                            else
                                                matlab.EvaluateAsString("obj.Across("+(j+1).ToString()+")=across;");

                                            within.Clear();
                                            po.FindPairsWithin(within,(int)((double)nPairs*spacers[j]/spacers[0]),diameter,sep);
                                            matlab.EvaluateAsString("wGood=wGood+"+within.Count.ToString()+";");
                                            for(k=0;k<within.Count;k++)
                                            {
                                                cirs = (Circle[])within[k];

                                                cirs[0].CalcStats(corePix,opd.PixelFactor,doCosWin,out mean,out cov,out nValid,out nInvalid);
                                                matlab.EvaluateAsString("acir=struct('X', " + 
                                                    cirs[0].Center.X.ToString() + ", 'Y', " + 
                                                    cirs[0].Center.Y.ToString() + ", 'Diameter', " + 
                                                    (cirs[0].Radius*2.0f).ToString() + ", 'Nvalid', " + 
                                                    nValid.ToString() + ", 'Ninvalid', " + 
                                                    nInvalid.ToString() + ");");
                                                matlab.SetMatrix("temp",mean);
                                                matlab.EvaluateAsString("acir.Mean = temp;");
                                                matlab.SetMatrix("temp",cov);
                                                matlab.EvaluateAsString("acir.Cov = temp;");

                                                cirs[1].CalcStats(corePix,opd.PixelFactor,doCosWin,out mean,out cov,out nValid,out nInvalid);
                                                matlab.EvaluateAsString("bcir=struct('X', " + 
                                                    cirs[1].Center.X.ToString() + ", 'Y', " + 
                                                    cirs[1].Center.Y.ToString() + ", 'Diameter', " + 
                                                    (cirs[1].Radius*2.0f).ToString() + ", 'Nvalid', " + 
                                                    nValid.ToString() + ", 'Ninvalid', " + 
                                                    nInvalid.ToString() + ");");
                                                matlab.SetMatrix("temp",mean);
                                                matlab.EvaluateAsString("bcir.Mean = temp;");
                                                matlab.SetMatrix("temp",cov);
                                                matlab.EvaluateAsString("bcir.Cov = temp;");

                                                if(k==0)
                                                {
                                                    matlab.EvaluateAsString("within = struct('A', acir, 'B', bcir);");
                                                    matlab.EvaluateAsString("within.Separation=" + sep.ToString() + ";");
                                                }
                                                else
                                                {
                                                    matlab.EvaluateAsString("within.A(" +(k+1).ToString()+ ")=acir;");
                                                    matlab.EvaluateAsString("within.B(" +(k+1).ToString()+ ")=bcir;");
                                                }
                                            }
                                            if(j==0)
                                                matlab.EvaluateAsString("obj.Within=within;");
                                            else
                                                matlab.EvaluateAsString("obj.Within("+(j+1).ToString()+")=within;");
                                        }
                                        ctAll++;
                                        if(ctAll==1)
                                            matlab.EvaluateAsString("all.Leaves=obj;");
                                        else
                                            matlab.EvaluateAsString("all.Leaves("+ctAll.ToString()+")=obj;");
                                        if(hasNoShadows)
                                        {
                                            ctUni++;
                                            if(ctUni==1)
                                                matlab.EvaluateAsString("uni.Leaves=obj;");
                                            else
                                                matlab.EvaluateAsString("uni.Leaves("+ctUni.ToString()+")=obj;");
                                        }
                                        if(hasShadows)
                                        {
                                            ctShad++;
                                            if(ctShad==1)
                                                matlab.EvaluateAsString("shad.Leaves=obj;");
                                            else
                                                matlab.EvaluateAsString("shad.Leaves("+ctShad.ToString()+")=obj;");
                                        }
                                    }
                                }
                            }

                            corePix.Dispose();
                            System.GC.Collect();
                        }
                        matlab.EvaluateAsString("save e:/data all uni shad;");
                        //matlab.EvaluateAsString("a=all; u=uni; s=shad; load e:/data2; a=[all,a]; u=[uni,u]; s=[shad,s]; load e:/data1; all=[all,a]; uni=[uni,u]; shad=[shad,s]; save e:/data all uni shad;");
                    }
                }
            }
        }
        private void mBatchExportCircles_Click(object sender,System.EventArgs e)
        {
            Cursor = Cursors.WaitCursor;

            BmgNet.ColorSpace[] spaces= new BmgNet.ColorSpace[] { ColorSpace.LogLmsOpp };
            if(OfdBatch==null)
                OfdBatch = new OpenFileDialog();
            OfdBatch.Multiselect = true;
            OfdBatch.Filter = "Object Parser Files | *.ObjParser";
            if(OfdBatch.ShowDialog()==DialogResult.OK)
            {
                string[] fnames = OfdBatch.FileNames;
                if(fnames != null)
                {
                    EngMATAccess matlab=null;
                    bool proceed = true;
                    try
                    {
                        matlab = ObjectParserData.Matlab;
                    }
                    catch
                    {
                        proceed = false;
                        MessageBox.Show(this,"Matlab could not be started.");
                    }

                    if(proceed && !matlab.Active)
                    {
                        proceed = false;
                        MessageBox.Show(this,"Matlab is not active.");
                    }

                    if(proceed)
                    {
                        int radiusSize = 6;
                        int nValid,nInvalid;
                        double[] mean;
                        double[,] cov;
                        ParsedObject pobj;
                        PolygonF poly;
                        Circle[] circles;
                        Circle cir;
                        int errmsg;
                        int i,j,k,l,ct;
                        for(ct=0;ct<fnames.Length;ct++)
                        {
                            ObjectParserData opd = ObjectParserData.Deserialize(fnames[ct], this, SerializationType.Binary);
                            Ushort3 corePix = Ushort3.FromPng16(opd.Imagename,out errmsg);
                            if(corePix==null)
                                MessageBox.Show("Break analysis.  Image did not load.  Fix data file.");
                            CategoryNode cn = opd.RootCategory.GetSubRecursive("Leaves");
                            if(cn==null)
                                MessageBox.Show("No category named Leaves.  Break analysis.  Fix data file.");
                            //	Set up the data structure
                            matlab.EvaluateAsString("proj=struct('Name', '"+opd.ShortProjname+"', 'Leaves', [], 'Residue', []);");

                            PixelTagger[] residue = new PixelTagger[opd.Circles.Length];
                            for(i=0;i<residue.Length;i++)
                            {
                                residue[i] = new PixelTagger(opd.Circles[i]);
                                for(j=0;j<cn.Objects.Count;j++)
                                {
                                    pobj = cn.Objects[j];
                                    for(k=0;k<pobj.Polygons.Count;k++)
                                    {
                                        poly = pobj.Polygons[k];
                                        residue[i].RemovePix(poly.Pix);
                                    }
                                }
                                residue[i].RandomCirclesInPix(radiusSize,100,50000,false,out circles);
                                for(l=0;l<circles.Length;l++)
                                {
                                    cir = circles[l];
                                    cir.CalcStats(corePix,opd.PixelFactor,false,out mean,out cov,out nValid,out nInvalid);
                                    matlab.EvaluateAsString("cir=struct('X', " + 
                                            cir.Center.X.ToString() + ", 'Y', " + 
                                            cir.Center.Y.ToString() + ", 'Rad', " + 
                                            cir.Radius.ToString() + ", 'Nvalid', " + 
                                            nValid.ToString() + ", 'Ninvalid', " + 
                                            nInvalid.ToString() + ");");
                                    matlab.SetMatrix("temp",mean);
                                    matlab.EvaluateAsString("cir.Mean = temp;");
                                    matlab.SetMatrix("temp",cov);
                                    matlab.EvaluateAsString("cir.Cov = temp;");
                                    if(l==0)
                                        matlab.EvaluateAsString("cirs = cir;");
                                    else
                                        matlab.EvaluateAsString("cirs(" + (l+1).ToString() + ")=cir;");
                                }
                                matlab.EvaluateAsString("res = [];");
                                matlab.EvaluateAsString("res.X = "+opd.Circles[i].Center.X.ToString()+";");
                                matlab.EvaluateAsString("res.Y = "+opd.Circles[i].Center.Y.ToString()+";");
                                matlab.EvaluateAsString("res.Rad = "+opd.Circles[i].Radius.ToString()+";");
                                if(circles.Length>0)
                                    matlab.EvaluateAsString("res.Circles = cirs;");
                                else
                                    matlab.EvaluateAsString("res.Circles = [];");
                                if(i==0)
                                    matlab.EvaluateAsString("proj.Residue=res;");
                                else
                                    matlab.EvaluateAsString("proj.Residue("+(i+1).ToString()+")=res;");
                            }
                            matlab.EvaluateAsString("objs = [];");
                            int ctObj = 0;
                            for(j=0;j<cn.Objects.Count;j++)
                            {
                                pobj = cn.Objects[j];
                                if(pobj.CatData.Quality==2)
                                {
                                    bool hasShadows = false;
                                    bool hasNoShadows = true;
                                    for(k=0;k<pobj.Polygons.Count && !hasShadows;k++)
                                    {
                                        poly = pobj.Polygons[k];
                                        for(l=0;l<poly.Contours.Count && !hasShadows;l++)
                                        {
                                            if(poly.Contours[l].CatData.ShadowBorder==2)
                                                hasNoShadows = false;
                                            else if(poly.Contours[l].CatData.ShadowBorder==2 || poly.Contours[l].CatData.ShadowBorder==3)
                                            {
                                                hasNoShadows = false;
                                                hasShadows = true;
                                            }
                                        }
                                    }
                                    if(hasShadows)
                                    {
                                        ctObj++;
                                        matlab.EvaluateAsString("obj=struct('Name', '"+ pobj.Name +"', 'Area', "+pobj.Area.ToString()+");");
                                        for(k=0;k<pobj.Polygons.Count;k++)
                                        {
                                            poly = pobj.Polygons[k];
                                            matlab.EvaluateAsString("poly=struct('Number', " +  k.ToString() + ");");
                                            matlab.EvaluateAsString("poly.Circles=[];");
                                            poly.Pix.RandomCirclesInPix(radiusSize,100,10000,false,out circles);
                                            for(l=0;l<circles.Length;l++)
                                            {
                                                cir = circles[l];
                                                cir.CalcStats(corePix,opd.PixelFactor,false,out mean,out cov,out nValid,out nInvalid);
                                                matlab.EvaluateAsString("cir=struct('X', " + 
                                                        cir.Center.X.ToString() + ", 'Y', " + 
                                                        cir.Center.Y.ToString() + ", 'Rad', " + 
                                                        cir.Radius.ToString() + ", 'Nvalid', " + 
                                                        nValid.ToString() + ", 'Ninvalid', " + 
                                                        nInvalid.ToString() + ");");
                                                matlab.SetMatrix("temp",mean);
                                                matlab.EvaluateAsString("cir.Mean = temp;");
                                                matlab.SetMatrix("temp",cov);
                                                matlab.EvaluateAsString("cir.Cov = temp;");
                                                if(l==0)
                                                    matlab.EvaluateAsString("cirs = cir;");
                                                else
                                                    matlab.EvaluateAsString("cirs(" + (l+1).ToString() + ")=cir;");
                                            }
                                            if(circles.Length>0)
                                                matlab.EvaluateAsString("poly.Circles = cirs; clear cir; clear cirs;");
                                            else
                                                matlab.EvaluateAsString("poly.Circles = [];");
                                            if(k==0)
                                                matlab.EvaluateAsString("polys = poly;");
                                            else
                                                matlab.EvaluateAsString("polys(" + (k+1).ToString() + ")=poly;");
                                        }
                                        matlab.EvaluateAsString("obj.Polys=polys; clear polys; clear poly;");
                                        if(ctObj==1)
                                            matlab.EvaluateAsString("objs = obj;");
                                        else
                                            matlab.EvaluateAsString("objs(" + (ctObj).ToString() + ")=obj;");
                                    }
                                }
                            }
                            matlab.EvaluateAsString("proj.Leaves = objs;");
                            if(ct==0)
                                matlab.EvaluateAsString("data = proj;");
                            else
                                matlab.EvaluateAsString("data(" + (ct+1).ToString() + ")=proj;");
                            corePix.Dispose();
                            opd = null;
                            System.GC.Collect();
                            //System.GC.WaitForPendingFinalizers();
                        }
                        matlab.EvaluateAsString("save e:/CircleS1 data;");
                    }
                }
            }
        }
        private void mBatchFullObsRibbons_Click(object sender,System.EventArgs e)
        {
            Cursor = Cursors.WaitCursor;

            BmgNet.ColorSpace[] spaces= new BmgNet.ColorSpace[] { ColorSpace.LogLmsOpp };
            if(OfdBatch==null)
                OfdBatch = new OpenFileDialog();
            OfdBatch.Multiselect = true;
            OfdBatch.Filter = "Object Parser Files | *.ObjParser";
            if(OfdBatch.ShowDialog()==DialogResult.OK)
            {
                string[] fnames = OfdBatch.FileNames;
                if(fnames != null)
                {
                    EngMATAccess matlab=null;
                    bool proceed = true;
                    try
                    {
                        matlab = ObjectParserData.Matlab;
                    }
                    catch
                    {
                        proceed = false;
                        MessageBox.Show(this,"Matlab could not be started.");
                    }

                    if(proceed)
                    {
                        int i,j,k,ct;

                        int minLength=32;
                        ArrayList ribs = new ArrayList();
                        ArrayList secs = new ArrayList();

                        Ushort3 corePix=null;
                        ObjectParserData opd;
                        CategoryNode cn;
                        //	For exporting the ribbons to Matlab
                        double[,] included;
                        double[,] ribLogLum;
                        double[,] ribLogYb;
                        double[,] ribLogRg;
                        double[,] spine;
                        int ribLength;
                        double heightProportion = 0.1;

                        for(ct=0;ct<fnames.Length;ct++)
                        {
                            opd = ObjectParserData.Deserialize(fnames[ct], this, SerializationType.Binary);

                            string name = opd.Imagename;
                            string shortProjName = opd.ShortProjname;

                            int errmsg;
                            corePix = Ushort3.FromPng16(name,out errmsg);
                            opd.ImageWidth = corePix.Nj;
                            opd.ImageHeight = corePix.Ni;

                            System.GC.Collect();

                            //  BOUNDARY RIBBONS
                            //	Set up the data structure
                            matlab.EvaluateAsString(
                                "cRibs=struct('IsValid', [], 'LogLum', [], 'LogYb', [], 'LogRg', [],"
							+"'Spine', [], 'RibbonLength', [], 'DirectionalDistances', [], "
							+"'ParsedObject', [], 'Project', [], 'PoDiameter', []);");
                            cn = opd.RootCategory.GetSubRecursive("Leaves");
                            if(cn!=null)
                            {
                                cn.GetFullContourRibbons(
                                    true,ribs,minLength,1.0f,heightProportion,
                                    corePix,opd.PixelFactor,1.0f,spaces);
                            }

                            Ribbon rib;
                            int ii;
                            for(i=0;i<ribs.Count;i++)
                            {
                                //	Get the active ribbon
                                rib = (Ribbon)ribs[i];
                                ribLength = rib.Spine.Length;
                                int ribHeight = rib.DirectionalDistances.Length;

                                //	Allocate memory
                                included = new double[ribHeight,ribLength];
                                ribLogLum = new double[ribHeight,ribLength];
                                ribLogYb = new double[ribHeight,ribLength];
                                ribLogRg = new double[ribHeight,ribLength];
                                spine = new double[ribLength,2];

                                System.GC.Collect();

                                //	For the length of the active ribbon
                                for(j=0;j<ribLength;j++)
                                {
                                    spine[j,0] = (double)rib.Spine[j].X;
                                    spine[j,1] = (double)rib.Spine[j].Y;
                                    //	For each directional distance
                                    for(k=0;k<ribHeight;k++)
                                    {
                                        if(rib.PixelIncluded[k,j])
                                            included[k,j]=1.0;
                                        else
                                        {
                                            included[k,j]=0.0;
                                            rib.LogLum[k,j] = rib.MeanLogLum;
                                            rib.LogYb[k,j] = rib.MeanLogYb;
                                            rib.LogRg[k,j] = rib.MeanLogRg;
                                        }
                                    }
                                }
                                double[] dirDistances = new double[rib.DirectionalDistances.Length];
                                for(k=0; k<dirDistances.Length; k++)
                                    dirDistances[k] = (double)rib.DirectionalDistances[k];
                                //ii = i + 1 + ctPast;
                                ii = i+1;
                                //	Send Ribbons to Matlab
                                matlab.SetMatrix("temp",included);
                                matlab.EvaluateAsString("cRibs(" + ii.ToString() + ").IsValid=logical(temp);");
                                matlab.SetMatrix("temp",rib.LogLum);
                                matlab.EvaluateAsString("cRibs(" + ii.ToString() + ").LogLum=single(temp);");
                                matlab.SetMatrix("temp",rib.LogYb);
                                matlab.EvaluateAsString("cRibs(" + ii.ToString() + ").LogYb=single(temp);");
                                matlab.SetMatrix("temp",rib.LogRg);
                                matlab.EvaluateAsString("cRibs(" + ii.ToString() + ").LogRg=single(temp);");
                                matlab.SetMatrix("temp",spine);
                                matlab.EvaluateAsString("cRibs(" + ii.ToString() + ").Spine=single(temp);");
                                matlab.SetMatrix("temp",rib.SecondAngularDerivative);
                                matlab.EvaluateAsString("cRibs(" + ii.ToString() + ").Curv=single(temp);");
                                matlab.SetMatrix("temp",dirDistances);
                                matlab.EvaluateAsString("cRibs(" + ii.ToString() + ").DirectionalDistances=single(temp);");
                                matlab.EvaluateAsString("cRibs(" + ii.ToString() + ").RibbonLength="+ribLength.ToString()+";");
                                matlab.EvaluateAsString("cRibs(" + ii.ToString() + ").Category='"+rib.CategoryName+"';");
                                matlab.EvaluateAsString("cRibs(" + ii.ToString() + ").ParsedObject='"+rib.PoName+"';");
                                matlab.EvaluateAsString("cRibs(" + ii.ToString() + ").Project='"+rib.ProjName+"';");
                                matlab.EvaluateAsString("cRibs(" + ii.ToString() + ").PoDiameter="+rib.PoDiameter.ToString()+";");
                                if(rib.PixNeg_Mean!= null)
                                {
                                    matlab.SetMatrix("temp",rib.PixNeg_Mean);
                                    matlab.EvaluateAsString("cRibs(" + ii.ToString() + ").PixNeg_Mean=single(temp);");
                                    matlab.SetMatrix("temp",rib.PixNeg_Cov);
                                    matlab.EvaluateAsString("cRibs(" + ii.ToString() + ").PixNeg_Cov=single(temp);");
                                    matlab.EvaluateAsString("cRibs(" + ii.ToString() + ").PixNeg_N="+rib.PixNeg.NumPts.ToString()+";");
                                }
                                if(rib.PixPos_Mean!= null)
                                {
                                    matlab.SetMatrix("temp",rib.PixPos_Mean);
                                    matlab.EvaluateAsString("cRibs(" + ii.ToString() + ").PixPos_Mean=single(temp);");
                                    matlab.SetMatrix("temp",rib.PixPos_Cov);
                                    matlab.EvaluateAsString("cRibs(" + ii.ToString() + ").PixPos_Cov=single(temp);");
                                    matlab.EvaluateAsString("cRibs(" + ii.ToString() + ").PixPos_N="+rib.PixPos.NumPts.ToString()+";");
                                }
                                ((ContourCategorizationData)rib.CatData).SendToMatlab(matlab,"cRibs(" + ii.ToString() + ")");

                                ribs[i]=null;

                                System.GC.Collect();
                            }
                            ribs.Clear();
                            System.GC.Collect();
                            matlab.EvaluateAsString("clear temp;");
                            matlab.EvaluateAsString("save e:/temp/Contours" +shortProjName+" cRibs;");
                            matlab.EvaluateAsString("clear cRibs");

                            //  SURFACE RIBBONS
                            //	Set up the data structure
                            matlab.EvaluateAsString(
                                "bRibs=struct('IsValid', [], 'LogLum', [], 'LogYb', [], 'LogRg', [],"
							+"'Spine', [], 'RibbonLength', [], 'DirectionalDistances', [], "
							+"'ParsedObject', [], 'Project', [], 'PoDiameter', []);");

                            if(cn!=null)
                            {
                                cn.GetFullSurfaceRibbons(
                                    true,ribs,minLength,1.0f,heightProportion,
                                    corePix,opd.PixelFactor,1.0f,spaces);
                            }
                            corePix.Dispose();
                            corePix = null;
                            opd = null;
                            cn = null;
                            System.GC.Collect();

                            for(i=0;i<ribs.Count;i++)
                            {
                                //	Get the active ribbon
                                rib = (Ribbon)ribs[i];
                                ribLength = rib.Spine.Length;
                                int ribHeight = rib.DirectionalDistances.Length;

                                //	Allocate memory
                                included = new double[ribHeight,ribLength];
                                ribLogLum = new double[ribHeight,ribLength];
                                ribLogYb = new double[ribHeight,ribLength];
                                ribLogRg = new double[ribHeight,ribLength];
                                spine = new double[ribLength,2];

                                System.GC.Collect();

                                //	For the length of the active ribbon
                                for(j=0;j<ribLength;j++)
                                {
                                    spine[j,0] = (double)rib.Spine[j].X;
                                    spine[j,1] = (double)rib.Spine[j].Y;
                                    //	For each directional distance
                                    for(k=0;k<ribHeight;k++)
                                    {
                                        if(rib.PixelIncluded[k,j])
                                            included[k,j]=1.0;
                                        else
                                        {
                                            included[k,j]=0.0;
                                            rib.LogLum[k,j] = rib.MeanLogLum;
                                            rib.LogYb[k,j] = rib.MeanLogYb;
                                            rib.LogRg[k,j] = rib.MeanLogRg;
                                        }
                                    }
                                }
                                double[] dirDistances = new double[rib.DirectionalDistances.Length];
                                for(k=0;k<dirDistances.Length;k++)
                                    dirDistances[k] = (double)rib.DirectionalDistances[k];
                                //ii = i + 1 + ctPast;
                                ii = i+1;
                                //	Send Ribbons to Matlab
                                matlab.SetMatrix("temp",included);
                                matlab.EvaluateAsString("bRibs(" + ii.ToString() + ").IsValid=logical(temp);");
                                matlab.SetMatrix("temp",rib.LogLum);
                                matlab.EvaluateAsString("bRibs(" + ii.ToString() + ").LogLum=single(temp);");
                                matlab.SetMatrix("temp",rib.LogYb);
                                matlab.EvaluateAsString("bRibs(" + ii.ToString() + ").LogYb=single(temp);");
                                matlab.SetMatrix("temp",rib.LogRg);
                                matlab.EvaluateAsString("bRibs(" + ii.ToString() + ").LogRg=single(temp);");
                                matlab.SetMatrix("temp",spine);
                                matlab.EvaluateAsString("bRibs(" + ii.ToString() + ").Spine=single(temp);");
                                matlab.SetMatrix("temp",rib.SecondAngularDerivative);
                                matlab.EvaluateAsString("bRibs(" + ii.ToString() + ").Curv=single(temp);");
                                matlab.SetMatrix("temp",dirDistances);
                                matlab.EvaluateAsString("bRibs(" + ii.ToString() + ").DirectionalDistances=single(temp);");
                                matlab.EvaluateAsString("bRibs(" + ii.ToString() + ").RibbonLength="+ribLength.ToString()+";");
                                matlab.EvaluateAsString("bRibs(" + ii.ToString() + ").Category='"+rib.CategoryName+"';");
                                matlab.EvaluateAsString("bRibs(" + ii.ToString() + ").ParsedObject='"+rib.PoName+"';");
                                matlab.EvaluateAsString("bRibs(" + ii.ToString() + ").Project='"+rib.ProjName+"';");
                                matlab.EvaluateAsString("bRibs(" + ii.ToString() + ").PoDiameter="+rib.PoDiameter.ToString()+";");
                                if(rib.PixNeg_Mean!= null)
                                {
                                    matlab.SetMatrix("temp",rib.PixNeg_Mean);
                                    matlab.EvaluateAsString("bRibs(" + ii.ToString() + ").PixNeg_Mean=single(temp);");
                                    matlab.SetMatrix("temp",rib.PixNeg_Cov);
                                    matlab.EvaluateAsString("bRibs(" + ii.ToString() + ").PixNeg_Cov=single(temp);");
                                    matlab.EvaluateAsString("bRibs(" + ii.ToString() + ").PixNeg_N="+rib.PixNeg.NumPts.ToString()+";");
                                }
                                if(rib.PixPos_Mean!= null)
                                {
                                    matlab.SetMatrix("temp",rib.PixPos_Mean);
                                    matlab.EvaluateAsString("bRibs(" + ii.ToString() + ").PixPos_Mean=single(temp);");
                                    matlab.SetMatrix("temp",rib.PixPos_Cov);
                                    matlab.EvaluateAsString("bRibs(" + ii.ToString() + ").PixPos_Cov=single(temp);");
                                    matlab.EvaluateAsString("bRibs(" + ii.ToString() + ").PixPos_N="+rib.PixPos.NumPts.ToString()+";");
                                }
                                ((ObjectCategorizationData)rib.CatData).SendToMatlab(matlab,"bRibs(" + ii.ToString() + ")");

                                ribs[i]=null;

                                System.GC.Collect();
                            }
                            ribs.Clear();
                            System.GC.Collect();
                            matlab.EvaluateAsString("clear temp;");
                            matlab.EvaluateAsString("save e:/temp/Boundaries" +shortProjName+" bRibs;");
                            matlab.EvaluateAsString("clear bRibs");
                            matlab.EvaluateAsString("pack;");
                        }
                        matlab.EvaluateAsString("clear temp;");
                        matlab.EvaluateAsString("disp cRibs");
                    }
                }
            }
            System.GC.Collect();
            Cursor = Cursors.Default;
        }
        private void mBatchExportContourRibbonsFull_Click(object sender,System.EventArgs e)
        {
            Cursor = Cursors.WaitCursor;

            BmgNet.ColorSpace[] spaces= new BmgNet.ColorSpace[] { ColorSpace.LogLmsOpp };
            if(OfdBatch==null)
                OfdBatch = new OpenFileDialog();
            OfdBatch.Multiselect = true;
            OfdBatch.Filter = "Object Parser Files | *.ObjParser";
            if(OfdBatch.ShowDialog()==DialogResult.OK)
            {
                string[] fnames = OfdBatch.FileNames;
                if(fnames != null)
                {
                    EngMATAccess matlab=null;
                    bool proceed = true;
                    try
                    {
                        matlab = ObjectParserData.Matlab;
                    }
                    catch
                    {
                        proceed = false;
                        MessageBox.Show(this,"Matlab could not be started.");
                    }

                    if(proceed)
                    {
                        int i,j,k,ct,ctPast=0;

                        int minLength=32;
                        ArrayList ribs = new ArrayList();
                        ArrayList secs = new ArrayList();

                        //	THE ACTUAL CODE:
                        float[] dd = new float[] {-10.0f, -9.0f, -8.0f, -7.0f, -6.0f, -5.0f, -4.0f, -3.0f, -2.0f, -1.0f, 0.0f,
													 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f};
                        double[,] dirDistances = new double[dd.Length,1];
                        for(i=0;i<dd.Length;i++)
                            dirDistances[i,0] = (double)dd[i];
                        int ribHeight=dd.Length;

                        Ushort3 corePix=null;
                        Complex2f lg = Complex2f.NaturalLogGabor(25);
                        Complex2f cross = Complex2f.Cross(25);
                        ComplexF val;
                        int filterLength = 15;
                        int nfilters = 3;
                        float filtoff = (float)filterLength/3.0f;
                        ComplexD[][,] filters = new ComplexD[nfilters][,];
                        PointF[] filterOffsets = new PointF[11];
                        for(i=0;i<3;i++)
                            filters[i] = new ComplexD[lg.Ni,lg.Nj];
                        for(i=0;i<lg.Ni;i++)
                        {
                            for(j=0;j<lg.Nj;j++)
                            {
                                val = lg[i,j];
                                //  Parallel filters
                                filters[0][i,j] = new ComplexD(val);
                                //  Perpendicular filter
                                filters[1][j,i] = new ComplexD(val);
                                //  Cross filter
                                filters[2][i,j] = new ComplexD(cross[i,j]);
                            }
                        }

                        //  Contour filters have no offset
                        filterOffsets[0] = new PointF(0.0f,0.0f);
                        filterOffsets[1] = new PointF(0.0f,0.0f);
                        filterOffsets[2] = new PointF(0.0f,0.0f);

                        ObjectParserData opd;
                        CategoryNode cn;
                        //	For exporting the ribbons to Matlab
                        double[,] included;
                        double[,] ribLogLum;
                        double[,] ribLogYb;
                        double[,] ribLogRg;
                        double[,] spine;
                        int ribLength;

                        for(ct=0;ct<fnames.Length;ct++)
                        {
                            //	Set up the data structure
                            matlab.EvaluateAsString(
                                "Ribbons=struct('IsValid', [], 'LogLum', [], 'LogYb', [], 'LogRg', [],"
							+"'Spine', [], 'RibbonLength', [], 'DirectionalDistances', [], "
							+"'ParsedObject', [], 'Project', []);");

                            opd = ObjectParserData.Deserialize(fnames[ct], this, SerializationType.Binary);

                            string name = opd.Imagename;
                            string shortProjName = opd.ShortProjname;

                            int errmsg;
                            corePix = Ushort3.FromPng16(name,out errmsg);
                            opd.ImageWidth = corePix.Nj;
                            opd.ImageHeight = corePix.Ni;

                            System.GC.Collect();

                            cn = opd.RootCategory.GetSubRecursive("Leaves");
                            if(cn!=null)
                            {
                                cn.GetFullContourRibbons(
                                    true,ribs,minLength,1.0f,
                                    corePix,opd.PixelFactor,
                                    dd,1.0f,spaces,filters,filterLength,filterOffsets);
                            }
                            corePix.Dispose();
                            corePix = null;
                            opd = null;
                            cn = null;
                            System.GC.Collect();

                            Ribbon rib;
                            int ii,l;
                            for(i=0;i<ribs.Count;i++)
                            {
                                //	Get the active ribbon
                                rib = (Ribbon)ribs[i];
                                ribLength = rib.Spine.Length;

                                //	Allocate memory
                                included = new double[ribHeight,ribLength];
                                ribLogLum = new double[ribHeight,ribLength];
                                ribLogYb = new double[ribHeight,ribLength];
                                ribLogRg = new double[ribHeight,ribLength];
                                spine = new double[ribLength,2];

                                System.GC.Collect();

                                //	For the length of the active ribbon
                                for(j=0;j<ribLength;j++)
                                {
                                    spine[j,0] = (double)rib.Spine[j].X;
                                    spine[j,1] = (double)rib.Spine[j].Y;
                                    //	For each directional distance
                                    for(k=0;k<ribHeight;k++)
                                    {
                                        if(rib.PixelIncluded[k,j])
                                            included[k,j]=1.0;
                                        else
                                        {
                                            included[k,j]=0.0;
                                            rib.LogLum[k,j] = rib.MeanLogLum;
                                            rib.LogYb[k,j] = rib.MeanLogYb;
                                            rib.LogRg[k,j] = rib.MeanLogRg;
                                        }
                                    }
                                }
                                //ii = i + 1 + ctPast;
                                ii = i+1;
                                //	Send Ribbons to Matlab
                                matlab.SetMatrix("temp",included);
                                matlab.EvaluateAsString("Ribbons(" + ii.ToString() + ").IsValid=temp;");
                                matlab.SetMatrix("temp",rib.LogLum);
                                matlab.EvaluateAsString("Ribbons(" + ii.ToString() + ").LogLum=temp;");
                                matlab.SetMatrix("temp",rib.LogYb);
                                matlab.EvaluateAsString("Ribbons(" + ii.ToString() + ").LogYb=temp;");
                                matlab.SetMatrix("temp",rib.LogRg);
                                matlab.EvaluateAsString("Ribbons(" + ii.ToString() + ").LogRg=temp;");
                                matlab.SetMatrix("temp",spine);
                                matlab.EvaluateAsString("Ribbons(" + ii.ToString() + ").Spine=temp;");
                                matlab.SetMatrix("temp",dirDistances);
                                matlab.EvaluateAsString("Ribbons(" + ii.ToString() + ").DirectionalDistances=temp;");
                                for(j=0;j<3;j++)
                                    for(k=0;k<filters.Length;k++)
                                    {
                                        ComplexD[] filt = rib.Filters[k][j];
                                        double[,] f = new double[2,filt.Length];
                                        for(l=0;l<rib.Spine.Length;l++)
                                        {
                                            f[0,l] = filt[l].Real;
                                            f[1,l] = filt[l].Imag;
                                        }
                                        matlab.SetMatrix("temp",f);
                                        matlab.EvaluateAsString("temp = temp(1,:) + temp(2,:)*1i;");
                                        matlab.EvaluateAsString("Ribbons(" + ii.ToString() + ").Filter{"+
                                            Convert.ToString(k+1)+","+
                                            Convert.ToString(j+1)+"}=temp;");
                                    }
                                matlab.EvaluateAsString("Ribbons(" + ii.ToString() + ").RibbonLength="+ribLength.ToString()+";");
                                matlab.EvaluateAsString("Ribbons(" + ii.ToString() + ").Category='"+rib.CategoryName+"';");
                                matlab.EvaluateAsString("Ribbons(" + ii.ToString() + ").ParsedObject='"+rib.PoName+"';");
                                matlab.EvaluateAsString("Ribbons(" + ii.ToString() + ").Project='"+rib.ProjName+"';");
                                ((ContourCategorizationData)rib.CatData).SendToMatlab(matlab,"Ribbons(" + ii.ToString() + ")");

                                ribs[i]=null;

                                System.GC.Collect();
                            }
                            ctPast+=ribs.Count;
                            ribs.Clear();
                            System.GC.Collect();
                            matlab.EvaluateAsString("clear temp;");
                            matlab.EvaluateAsString("save e:/temp/Contours" +shortProjName+" Ribbons;");
                            matlab.EvaluateAsString("clear Ribbons");
                            matlab.EvaluateAsString("pack;");
                        }
                        matlab.EvaluateAsString("clear temp;");
                        matlab.EvaluateAsString("disp Ribbons");
                    }
                }
            }
            System.GC.Collect();
            Cursor = Cursors.Default;
        }
        private void mBatchExportBoundaryRibbonsFull_Click(object sender,System.EventArgs e)
        {
            Cursor = Cursors.WaitCursor;

            BmgNet.ColorSpace[] spaces= new BmgNet.ColorSpace[] { ColorSpace.LogLmsOpp };
            if(OfdBatch==null)
                OfdBatch = new OpenFileDialog();
            OfdBatch.Multiselect = true;
            OfdBatch.Filter = "Object Parser Files | *.ObjParser";
            if(OfdBatch.ShowDialog()==DialogResult.OK)
            {
                string[] fnames = OfdBatch.FileNames;
                if(fnames != null)
                {
                    EngMATAccess matlab=null;
                    bool proceed = true;
                    try
                    {
                        matlab = ObjectParserData.Matlab;
                    }
                    catch
                    {
                        proceed = false;
                        MessageBox.Show(this,"Matlab could not be started.");
                    }

                    if(proceed && !matlab.Active)
                    {
                        proceed = false;
                        MessageBox.Show(this,"Matlab is not active.");
                    }

                    if(proceed)
                    {
                        int i,j,k,ct,ctPast=0;

                        int minLength=32;
                        ArrayList ribs = new ArrayList();
                        ArrayList secs = new ArrayList();

                        //	THE ACTUAL CODE:
                        float[] dd = new float[] {-10.0f, -9.0f, -8.0f, -7.0f, -6.0f, -5.0f, -4.0f, -3.0f, -2.0f, -1.0f, 0.0f,
													 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f};
                        double[,] dirDistances = new double[dd.Length,1];
                        for(i=0;i<dd.Length;i++)
                            dirDistances[i,0] = (double)dd[i];
                        int ribHeight=dd.Length;

                        Ushort3 corePix=null;
                        Complex2f lg = Complex2f.NaturalLogGabor(25);
                        Complex2f cross = Complex2f.Cross(25);
                        ComplexF val;
                        int filterLength = 15;
                        int nfilters = 3;
                        float filtoff = (float)filterLength/3.0f;
                        ComplexD[][,] filters = new ComplexD[nfilters][,];
                        PointF[] filterOffsets = new PointF[11];
                        for(i=0;i<3;i++)
                            filters[i] = new ComplexD[lg.Ni,lg.Nj];
                        for(i=0;i<lg.Ni;i++)
                        {
                            for(j=0;j<lg.Nj;j++)
                            {
                                val = lg[i,j];
                                //  Parallel filters
                                filters[0][i,j] = new ComplexD(val);
                                //  Perpendicular filter
                                filters[1][j,i] = new ComplexD(val);
                                //  Cross filter
                                filters[2][i,j] = new ComplexD(cross[i,j]);
                            }
                        }

                        //  Contour filters have no offset
                        filterOffsets[0] = new PointF(0.0f,0.0f);
                        filterOffsets[1] = new PointF(0.0f,0.0f);
                        filterOffsets[2] = new PointF(0.0f,0.0f);

                        ObjectParserData opd;
                        CategoryNode cn;
                        //	For exporting the ribbons to Matlab
                        double[,] included;
                        double[,] ribLogLum;
                        double[,] ribLogYb;
                        double[,] ribLogRg;
                        double[,] spine;
                        int ribLength;

                        for(ct=0;ct<fnames.Length;ct++)
                        {
                            //	Set up the data structure
                            matlab.EvaluateAsString(
                                "boundRibs=struct('IsValid', [], 'LogLum', [], 'LogYb', [], 'LogRg', [],"
							+"'Spine', [], 'RibbonLength', [], 'DirectionalDistances', [], "
							+"'ParsedObject', [], 'Project', []);");

                            opd = ObjectParserData.Deserialize(fnames[ct], this, SerializationType.Binary);
                            opd.TidyOwnedEdges();

                            string name = opd.Imagename;
                            string shortProjName = opd.ShortProjname;

                            int errmsg;
                            corePix = Ushort3.FromPng16(name,out errmsg);
                            opd.ImageWidth = corePix.Nj;
                            opd.ImageHeight = corePix.Ni;

                            System.GC.Collect();

                            cn = opd.RootCategory.GetSubRecursive("Leaves");
                            if(cn!=null)
                            {
                                cn.GetFullSurfaceRibbons(
                                    true,ribs,minLength,1.0f,
                                    corePix,opd.PixelFactor,
                                    dd,1.0f,spaces,filters,filterLength,filterOffsets);
                            }
                            corePix.Dispose();
                            corePix = null;
                            opd = null;
                            cn = null;
                            System.GC.Collect();

                            Ribbon rib;
                            int ii,l;
                            for(i=0;i<ribs.Count;i++)
                            {
                                //	Get the active ribbon
                                rib = (Ribbon)ribs[i];
                                ribLength = rib.Spine.Length;

                                //	Allocate memory
                                included = new double[ribHeight,ribLength];
                                ribLogLum = new double[ribHeight,ribLength];
                                ribLogYb = new double[ribHeight,ribLength];
                                ribLogRg = new double[ribHeight,ribLength];
                                spine = new double[ribLength,2];

                                System.GC.Collect();

                                //	For the length of the active ribbon
                                for(j=0;j<ribLength;j++)
                                {
                                    spine[j,0] = (double)rib.Spine[j].X;
                                    spine[j,1] = (double)rib.Spine[j].Y;
                                    //	For each directional distance
                                    for(k=0;k<ribHeight;k++)
                                    {
                                        if(rib.PixelIncluded[k,j])
                                            included[k,j]=1.0;
                                        else
                                        {
                                            included[k,j]=0.0;
                                            rib.LogLum[k,j] = rib.MeanLogLum;
                                            rib.LogYb[k,j] = rib.MeanLogYb;
                                            rib.LogRg[k,j] = rib.MeanLogRg;
                                        }
                                    }
                                }
                                //ii = i + 1 + ctPast;
                                ii = i+1;
                                //	Send Ribbons to Matlab
                                matlab.SetMatrix("temp",included);
                                matlab.EvaluateAsString("boundRibs(" + ii.ToString() + ").IsValid=temp;");
                                matlab.SetMatrix("temp",rib.LogLum);
                                matlab.EvaluateAsString("boundRibs(" + ii.ToString() + ").LogLum=temp;");
                                matlab.SetMatrix("temp",rib.LogYb);
                                matlab.EvaluateAsString("boundRibs(" + ii.ToString() + ").LogYb=temp;");
                                matlab.SetMatrix("temp",rib.LogRg);
                                matlab.EvaluateAsString("boundRibs(" + ii.ToString() + ").LogRg=temp;");
                                matlab.SetMatrix("temp",spine);
                                matlab.EvaluateAsString("boundRibs(" + ii.ToString() + ").Spine=temp;");
                                matlab.SetMatrix("temp",dirDistances);
                                matlab.EvaluateAsString("boundRibs(" + ii.ToString() + ").DirectionalDistances=temp;");
                                for(j=0;j<3;j++)
                                    for(k=0;k<filters.Length;k++)
                                    {
                                        ComplexD[] filt = rib.Filters[k][j];
                                        double[,] f = new double[2,filt.Length];
                                        for(l=0;l<rib.Spine.Length;l++)
                                        {
                                            f[0,l] = filt[l].Real;
                                            f[1,l] = filt[l].Imag;
                                        }
                                        matlab.SetMatrix("temp",f);
                                        matlab.EvaluateAsString("temp = temp(1,:) + temp(2,:)*1i;");
                                        matlab.EvaluateAsString("boundRibs(" + ii.ToString() + ").Filter{"+
                                            Convert.ToString(k+1)+","+
                                            Convert.ToString(j+1)+"}=temp;");
                                    }
                                matlab.EvaluateAsString("boundRibs(" + ii.ToString() + ").RibbonLength="+ribLength.ToString()+";");
                                matlab.EvaluateAsString("boundRibs(" + ii.ToString() + ").Category='"+rib.CategoryName+"';");
                                matlab.EvaluateAsString("boundRibs(" + ii.ToString() + ").ParsedObject='"+rib.PoName+"';");
                                matlab.EvaluateAsString("boundRibs(" + ii.ToString() + ").Project='"+rib.ProjName+"';");
                                ((ObjectCategorizationData)rib.CatData).SendToMatlab(matlab,"boundRibs(" + ii.ToString() + ")");

                                ribs[i]=null;

                                System.GC.Collect();
                            }
                            ctPast+=ribs.Count;
                            ribs.Clear();
                            System.GC.Collect();
                            matlab.EvaluateAsString("clear temp;");
                            matlab.EvaluateAsString("save e:/temp/Boundaries" +shortProjName+" boundRibs;");
                            matlab.EvaluateAsString("clear boundRibs");
                            matlab.EvaluateAsString("pack;");
                        }
                    }
                }
            }
            System.GC.Collect();
            Cursor = Cursors.Default;
        }
        private void mBatchExportStruct_Click(object sender,System.EventArgs e)
        {
            Cursor = Cursors.WaitCursor;

            if(OfdBatch==null)
                OfdBatch = new OpenFileDialog();
            OfdBatch.Multiselect = true;
            OfdBatch.Filter = "Object Parser Files | *.ObjParser";
            if(OfdBatch.ShowDialog()==DialogResult.OK)
            {
                string[] fnames = OfdBatch.FileNames;
                if(fnames != null)
                {
                    bool proceed = true;
                    EngMATAccess matlab = null;
                    try
                    {
                        matlab = ObjectParserData.Matlab;
                    }
                    catch
                    {
                        proceed = false;
                        MessageBox.Show(this,"Matlab could not be started.");
                    }

                    if(proceed)
                    {
                        int ct=0;

                        ObjectParserData opd;

                        for(ct=0;ct<fnames.Length;ct++)
                        {
                            opd = ObjectParserData.Deserialize(fnames[ct], this, SerializationType.Binary);
                            string varName = "data(" + (ct+1).ToString() + ").";
                            opd.ToMatlabStruct(varName,matlab);
                        }
                        matlab.EvaluateAsString("clear temp;");
                    }
                }
            }

            Cursor = Cursors.Default;
        }
        private void mMatlabOvals_Click(object sender,System.EventArgs e)
        {
            BmgNet.ColorSpace[] spaces= new BmgNet.ColorSpace[] { ColorSpace.LogLmsOpp };
            if(OfdBatch==null)
                OfdBatch = new OpenFileDialog();
            OfdBatch.Multiselect = true;
            OfdBatch.Filter = "Object Parser Files | *.ObjParser";
            if(OfdBatch.ShowDialog()==DialogResult.OK)
            {
                string[] fnames = OfdBatch.FileNames;
                if(fnames != null)
                {
                    EngMATAccess matlab=null;
                    bool proceed = true;
                    try
                    {
                        matlab = ObjectParserData.Matlab;
                    }
                    catch
                    {
                        proceed = false;
                        MessageBox.Show(this,"Matlab could not be started.");
                    }

                    if(proceed)
                    {
                        ParsedObjectList obs = new ParsedObjectList();
                        ArrayList means = new ArrayList();
                        ArrayList covs = new ArrayList();
                        ArrayList nActuals = new ArrayList();
                        Ushort3 corePix;
                        matlab.EvaluateAsString(
                            "data = struct('ProjectName', [], 'CategoryName', [], 'ObjectName', [], 'Mean', [], 'Cov', [], 'N', []);");
                        string dataStr;
                        ParsedObject po;
                        double[,] mu=new double[5,1];

                        int i,j,ct=0;
                        for(j=0;j<fnames.Length;j++)
                        {
                            ObjectParserData opd = ObjectParserData.Deserialize(fnames[j],this,SerializationType.Binary);
                            System.GC.Collect();

                            string name = opd.Imagename;

                            CategoryNode cn = opd.RootCategory.GetSubRecursive("Leaves");
                            if(cn!=null)
                            {
                                int errmsg;
                                corePix = Ushort3.FromPng16(name,out errmsg);

                                opd.ImageWidth = corePix.Nj;
                                opd.ImageHeight = corePix.Ni;

                                float scale = opd.Fstop*opd.Fstop*opd.ShutterRate/opd.IsoFilmSpeed*1000.0f;

                                if(scale <= 0.0f)
                                {
                                    scale = Single.NaN;
                                }
                                else
                                {
                                    cn.LmsOppStats(500,means,covs,nActuals,obs,corePix,scale,false);

                                    for(i=0;i<means.Count;i++)
                                    {
                                        ct++;
                                        dataStr = "data(" + ct.ToString() + ")";
                                        po = obs[i];

                                        //	Strings for identifying the object.
                                        matlab.EvaluateAsString(dataStr + ".ProjectName='"+po.Category.Owner.ShortProjname+"';");
                                        matlab.EvaluateAsString(dataStr + ".CategoryName='"+po.Category.Name+"';");
                                        matlab.EvaluateAsString(dataStr + ".ObjectName='"+po.Name+"';");

                                        //	Set the mean
                                        double[] mean = (double[])means[i];
                                        mu[0,0] = mean[0]; mu[1,0] = mean[1]; mu[2,0] = mean[2]; mu[3,0] = mean[3]; mu[4,0] = mean[4];
                                        matlab.SetMatrix("temp",mu);
                                        matlab.EvaluateAsString(dataStr + ".Mean=temp;");

                                        //	Set the cov
                                        matlab.SetMatrix("temp",((double[,])covs[i]));
                                        matlab.EvaluateAsString(dataStr + ".Cov=temp;");

                                        //	Set the number of pixels.
                                        matlab.EvaluateAsString(dataStr + ".N=" + ((int)nActuals[i]).ToString()+";");

                                        //	Set the categorization information
                                        matlab.EvaluateAsString(dataStr + ".DeadToLiving=" + po.CatData.DeadToLiving.ToString() + ";");
                                        matlab.EvaluateAsString(dataStr + ".Focused=" + po.CatData.Focused.ToString() + ";");
                                        matlab.EvaluateAsString(dataStr + ".Occluded=" + po.CatData.Occluded.ToString() + ";");
                                        matlab.EvaluateAsString(dataStr + ".Quality=" + po.CatData.Quality.ToString() + ";");
                                        matlab.EvaluateAsString(dataStr + ".RoughToSmooth=" + po.CatData.SmoothToRough.ToString() + ";");
                                        matlab.EvaluateAsString(dataStr + ".SharpShadowBoundary=" + po.CatData.SharpShadowBoundary.ToString() + ";");
                                        matlab.EvaluateAsString(dataStr + ".Specularized=" + po.CatData.Specularized.ToString() + ";");
                                        matlab.EvaluateAsString(dataStr + ".UniformToVariegated=" + po.CatData.UniformToVariegated.ToString() + ";");
                                    }
                                    means.Clear();
                                    covs.Clear();
                                    nActuals.Clear();
                                    obs.Clear();
                                }
                                corePix.Dispose();
                                corePix=null;
                            }
                            opd=null;
                            System.GC.Collect();
                        }
                        matlab.EvaluateAsString("clear temp;");
                    }
                }
            }
        }
        private void mMatlabSpines_Click(object sender,System.EventArgs e)
        {
            if(OfdBatch==null)
                OfdBatch = new OpenFileDialog();
            OfdBatch.Multiselect = true;
            OfdBatch.Filter = "Object Parser Files | *.ObjParser";
            if(OfdBatch.ShowDialog()==DialogResult.OK)
            {
                string[] fnames = OfdBatch.FileNames;
                if(fnames != null)
                {
                    EngMATAccess matlab=null;
                    bool proceed = true;
                    try
                    {
                        matlab = ObjectParserData.Matlab;
                    }
                    catch
                    {
                        proceed = false;
                        MessageBox.Show(this,"Matlab could not be started.");
                    }

                    if(proceed)
                    {
                        this.statusBar1.Text = "Processing.";
                        this.statusBar1.Refresh();
                        ParsedObjectList obs = new ParsedObjectList();
                        matlab.EvaluateAsString(
                            "data = struct('ProjectName', [], 'CategoryName', [], 'ObjectName', [], 'Npoly', [], 'Nbridge', [], 'Points', [], 'Orientation', [], 'Curvature', []);");
                        string dataStr;
                        ParsedObject po;
                        SurfaceBound sb;
                        SurfaceBoundList sbl;
                        float dpix = 1.0f;
                        double ksd = 1.0;

                        int i,j,k,l,ct=0;
                        for(j=0;j<fnames.Length;j++)
                        {
                            ObjectParserData opd = ObjectParserData.Deserialize(fnames[j],this,SerializationType.Binary);
                            System.GC.Collect();
                            if(opd.RootCategory!=null)
                            {
                                opd.RootCategory.InventoryParsedObjects(obs);
                                for(i=0;i<obs.Count;i++)
                                {
                                    po = obs[i];
                                    sbl = new SurfaceBoundList(po,dpix);
                                    if(sbl!=null)
                                        for(k=0;k<sbl.Count;k++)
                                        {
                                            sb = sbl[k];
                                            if(sb.IsValidSurface)
                                            {
                                                PointF[] spine = sb.MakeSingleSpine(dpix);
                                                if(spine!=null && spine.Length>1)
                                                {
                                                    ct++;
                                                    dataStr = "data("+ct.ToString()+").";
                                                    matlab.EvaluateAsString(dataStr + "ProjectName='" + opd.ShortProjname + "';");
                                                    matlab.EvaluateAsString(dataStr + "CategoryName='" + po.Category.Name + "';");
                                                    matlab.EvaluateAsString(dataStr + "ObjectName='" + po.Name + "';");
                                                    matlab.EvaluateAsString(dataStr + "Npoly=" + po.Polygons.Count.ToString() + ";");
                                                    matlab.EvaluateAsString(dataStr + "Nbridge=" + po.Bridges.Count.ToString() + ";");
                                                    matlab.EvaluateAsString(dataStr + "KernelSd=" + ksd.ToString() + ";");
                                                    //	Set the categorization information
                                                    matlab.EvaluateAsString(dataStr + "DeadToLiving=" + po.CatData.DeadToLiving.ToString() + ";");
                                                    matlab.EvaluateAsString(dataStr + "Focused=" + po.CatData.Focused.ToString() + ";");
                                                    matlab.EvaluateAsString(dataStr + "Occluded=" + po.CatData.Occluded.ToString() + ";");
                                                    matlab.EvaluateAsString(dataStr + "Quality=" + po.CatData.Quality.ToString() + ";");
                                                    matlab.EvaluateAsString(dataStr + "RoughToSmooth=" + po.CatData.SmoothToRough.ToString() + ";");
                                                    matlab.EvaluateAsString(dataStr + "SharpShadowBoundary=" + po.CatData.SharpShadowBoundary.ToString() + ";");
                                                    matlab.EvaluateAsString(dataStr + "Specularized=" + po.CatData.Specularized.ToString() + ";");
                                                    matlab.EvaluateAsString(dataStr + "UniformToVariegated=" + po.CatData.UniformToVariegated.ToString() + ";");

                                                    matlab.SetMatrix("temp",Util.ToDoubleArray(spine));
                                                    matlab.EvaluateAsString(dataStr + "Points=temp;");

                                                    double[,] temp = new double[spine.Length,1];
                                                    double[] or = new double[spine.Length];
                                                    Util.CalcOrientation(spine,or,ksd,true);
                                                    for(l=0;l<or.Length;l++)
                                                        temp[l,0] = or[l];
                                                    matlab.SetMatrix("temp",temp);
                                                    matlab.EvaluateAsString(dataStr + "Orientation=temp;");

                                                    double[] curv = new double[spine.Length];
                                                    Util.AngularDiff(or,curv,or.Length,true);
                                                    for(l=0;l<curv.Length;l++)
                                                        temp[l,0] = curv[l];
                                                    matlab.SetMatrix("temp",temp);
                                                    matlab.EvaluateAsString(dataStr + "Curvature=temp;");
                                                }
                                            }
                                        }
                                }
                            }
                            obs.Clear();
                            opd=null;
                            System.GC.Collect();
                        }
                        matlab.EvaluateAsString("clear temp;");
                        this.statusBar1.Text = "Ready.";
                        this.statusBar1.Refresh();
                    }
                }
            }
        }
        private void mMakeThumbnails_Click(object sender, System.EventArgs e)
        {
            if(OfdBatch==null)
                OfdBatch = new OpenFileDialog();
            OfdBatch.Multiselect = true;
            OfdBatch.Filter = "Object Parser Files | *.ObjParser";
            ImageCodecInfo codec = GetEncoderInfo("image/jpeg");
            Encoder encoder = Encoder.Quality;
            EncoderParameters pars = new EncoderParameters(1);
            pars.Param[0] = new EncoderParameter(encoder,100L);

            int iRow, iCol, iFile;
            Bitmap bmp, bmpThumbs, bmpThumbsPainted;
            Size grThumbs, szThumb;
            float left, top, right, bottom, width, height;
            float rw, rh, xc, yc;

            if (OfdBatch.ShowDialog() == DialogResult.OK)
            {
                string[] fnames = OfdBatch.FileNames;
                if (fnames != null && fnames.Length>0)
                {
                    string path = Util.RemoveFilenameFromPath(fnames[0]);
                    grThumbs = new Size((fnames.Length + 7) / 8, 8);
                    szThumb = new Size(200, 200);

                    bmpThumbs = new Bitmap((szThumb.Width + 2) * grThumbs.Width + 1, (szThumb.Height + 2) * grThumbs.Height + 1);
                    bmpThumbsPainted = new Bitmap(bmpThumbs.Size.Width, bmpThumbs.Size.Height);

                    //  Create a graphics object (device context) and paint event args
                    Graphics gThumbs = Graphics.FromImage(bmpThumbs);
                    //  Create a graphics object (device context) and paint event args 
                    Graphics gThumbsPainted = Graphics.FromImage(bmpThumbsPainted);

                    //  String for processing the display name of the altered image
                    string dname = "";
                    string dpath = "C:\\Data\\xIng01_DisplayImages_gc\\";

                    //  For each file
                    for (iFile = 0; iFile < fnames.Length; iFile++)
                    {
                        //  Get the grid location (zero based)
                        iCol = iFile % grThumbs.Width;
                        iRow = iFile / grThumbs.Width;

                        //  Determine blitting rectangle of destination
                        Rectangle rBlitDest = new Rectangle(1 + iCol * (szThumb.Width+2), 1 + iRow * (szThumb.Height+2), szThumb.Width, szThumb.Height);

                        //	Open display image and data
                        ObjectParserData opd = ObjectParserData.Deserialize(fnames[iFile], this, SerializationType.Binary);
                        //bmp = new Bitmap(opd.DisplayImagename);
                        dname = Util.RemovePathInfo(opd.DisplayImagename).Substring(0, 8);
                        bmp = new Bitmap(dpath + dname + ".jpg");

                        //  Make "Leaves" the active category.
                        CategoryNode cn = opd.RootCategory.GetSubRecursive("Leaves");
                        opd.ActiveCategory = cn;

                        //  Determine the bounding rect of the active category
                        RectangleF rBound = cn.GetBoundingRect(true);
                        left = rBound.Left;
                        top = rBound.Top;
                        right = rBound.Right;
                        bottom = rBound.Bottom;

                        //  -------------------------------------------
                        //  Determine the blitting rectangle of source
                        //  -------------------------------------------
                        if (left <= 0.0f)
                            left = 0.0f;
                        if (top <= 0.0f)
                            top = 0.0f;
                        if (right >= (float)opd.ImageWidth)
                            right = (float)(opd.ImageWidth - 1);
                        if (bottom >= (float)opd.ImageHeight)
                            bottom = (float)(opd.ImageHeight - 1);
                        width = right - left + 1.0f;
                        height = bottom - top + 1.0f;
                        rw = width / (float)szThumb.Width;
                        //lrw = Math.Log(rw);
                        rh = height / (float)szThumb.Height;
                        //lrh = Math.Log(rh);

                        //  Pick whether width or height determines the bounding rect (it's the one with the most highest ratio).
                        rh = rw = (float)Math.Max(rh, rw) * 0.8f;
                        width = (float)Math.Floor(0.5f + (float)szThumb.Width * rw);
                        height = (float)Math.Floor(0.5f + (float)szThumb.Height * rh);

                        //  Make sure the width and height are smaller than the size of the image
                        rh = (float)opd.ImageHeight / height;
                        rw = (float)opd.ImageWidth / width;
                        rh = rw = Math.Min(rh, rw);
                        if (rh <= 1.0f)
                        {
                            height = height * rh * 0.99f;
                            width = width * rw * 0.99f;
                        }
                        //  Compute the center
                        xc = (left + right) / 2.0f;
                        yc = (top + bottom) / 2.0f;

                        //  Compute the desired rectangle
                        left = (float)Math.Floor(xc - width / 2.0f);
                        right = (float)Math.Ceiling(xc + width / 2.0f);
                        top = (float)Math.Floor(yc - height / 2.0f);
                        bottom = (float)Math.Ceiling(yc + height / 2.0f);

                        //  Shift
                        if (left <= 0.0f)
                        {
                            right -= left;
                            left = 0.0f;
                        }
                        if (top <= 0.0f)
                        {
                            bottom -= top;
                            top = 0.0f;
                        }
                        if (right >= (float)opd.ImageWidth)
                        {
                            left -= (right - (float)(opd.ImageWidth - 1));
                            right = (float)(opd.ImageWidth - 1);
                        }
                        if (bottom >= (float)opd.ImageHeight)
                        {
                            top -= (bottom - (float)(opd.ImageHeight - 1));
                            bottom = (float)(opd.ImageHeight - 1);
                        }
                        Rectangle rBlitSrc = Rectangle.FromLTRB((int)left, (int)top, (int)right, (int)bottom);
                        //  -------------------------------------------

                        //  Paint image onto thumbnail
                        gThumbs.DrawImage(bmp, rBlitDest, rBlitSrc, GraphicsUnit.Pixel);

                        //  Paint categories besides leaves
                        for(int iCat=0; iCat<cn.Super.Sub.Count; iCat++)
                            if (cn != cn.Super.Sub[iCat])
                                SelectionRecord.Imprint(bmp, Color.FromArgb(100, 0, 0, 255), cn.Super.Sub[iCat], true);
                        //  Paint leaves
                        SelectionRecord.Imprint(bmp, Color.FromArgb(100, 255, 0, 0), cn, true);
                        //  Paint image onto thumbnail
                        gThumbsPainted.DrawImage(bmp, rBlitDest, rBlitSrc, GraphicsUnit.Pixel);
                    }

                    //  Save bitmap
                    bmpThumbs.Save(path + "/thumbs.jpg", codec, pars);
                    bmpThumbsPainted.Save(path + "/thumbsPainted.jpg", codec, pars);
                }
            }
        }
        private void mCreateShowoff_Click(object sender, System.EventArgs e)
        {
            if(OfdBatch==null)
                OfdBatch = new OpenFileDialog();
            OfdBatch.Multiselect = true;
            OfdBatch.Filter = "Object Parser Files | *.ObjParser";
            ImageCodecInfo codec = GetEncoderInfo("image/jpeg");
            Encoder encoder = Encoder.Quality;
            EncoderParameters pars = new EncoderParameters(1);
            pars.Param[0] = new EncoderParameter(encoder,100L);

            if(OfdBatch.ShowDialog()==DialogResult.OK)
            {
                string[] fnames = OfdBatch.FileNames;
                if(fnames != null)
                {
                    this.statusBar1.Text = "Processing.";
                    this.statusBar1.Refresh();
                    Bitmap bmp,bmpSmall;
                    Circle cir;
                    RectangleF rf;
                    int j;
                    for(j=0;j<fnames.Length;j++)
                    {
                        //	Open display image and data
                        ObjectParserData opd = ObjectParserData.Deserialize(fnames[j],this,SerializationType.Binary);
                        bmp = new Bitmap(opd.DisplayImagename);

                        //	Get info related to the image filepath
                        string path = Util.RemoveFilenameFromPath(opd.DisplayImagename);
                        string name = Util.RemoveExtension(Util.RemovePathInfo(opd.DisplayImagename));

                        //	Insure directories exist
                        if(!Directory.Exists(path + "/Jpeg"))
                            Directory.CreateDirectory(path + "/Jpeg");
                        if(!Directory.Exists(path + "/CroppedJpeg"))
                            Directory.CreateDirectory(path + "/CroppedJpeg");
                        if(!Directory.Exists(path + "/CroppedPaintedJpeg"))
                            Directory.CreateDirectory(path + "/CroppedPaintedJpeg");

                        //	Get the active circle's bounding rect.
                        cir = opd.Circles[opd.ActiveCircleInd];
                        rf = cir.BoundingRectF;
                        Graphics gg = Graphics.FromImage(bmp);
                        gg.DrawEllipse(CirclePen,rf);
                        bmp.Save(path + "/Jpeg/" + name + ".jpg",codec,pars);

                        //	Reload the display image
                        bmp = new Bitmap(opd.DisplayImagename);

                        rf = new RectangleF(Math.Max(0.0f,rf.Left-rf.Width),Math.Max(0.0f,rf.Top-rf.Height),
                            rf.Width*3.0f,rf.Height*3.0f);
                        if(rf.Right > (float)bmp.Width)
                            rf= new RectangleF(rf.Left,rf.Top,(float)bmp.Width-rf.Left-1.0f,rf.Height);
                        if(rf.Bottom > (float)bmp.Height)
                            rf= new RectangleF(rf.Left,rf.Top,rf.Width,(float)bmp.Height-rf.Top-1.0f);
                        Rectangle rect = new Rectangle((int)rf.Left,(int)rf.Top,(int)rf.Width,(int)rf.Height);
                        bmpSmall = new Bitmap(rect.Width,rect.Height);

                        //	Save the cropped region
                        Graphics g = Graphics.FromImage(bmpSmall);
                        g.DrawImage(bmp,new Rectangle(0,0,rect.Width,rect.Height),
                            rect.Left,rect.Top,rect.Width,rect.Height,GraphicsUnit.Pixel);
                        bmpSmall.Save(path + "/CroppedJpeg/" + name + ".jpg",codec,pars);

                        //	Save the painted region
                        SelectionRecord.Imprint(bmp,Color.FromArgb(50,255,0,0),opd.RootCategory,true);
                        g.DrawImage(bmp,new Rectangle(0,0,rect.Width,rect.Height),
                            rect.Left,rect.Top,rect.Width,rect.Height,GraphicsUnit.Pixel);
                        bmpSmall.Save(path + "/CroppedPaintedJpeg/" + name + ".jpg",codec,pars);

                        bmp=null;
                        g=null;
                        gg=null;
                        bmpSmall=null;
                        opd=null;
                        System.GC.Collect();
                    }
                    this.statusBar1.Text = "Ready.";
                    this.statusBar1.Refresh();
                }
            }
        }
        #endregion
        #region Buttons and Viewing Options
        private void bLinkMode_Click(object sender,System.EventArgs e)
        {
            if(Ptool!=null)
                Ptool.ToggleLinkMode();
        }
        private void bLinkMode_Paint(object sender,System.Windows.Forms.PaintEventArgs e)
        {
            PaintButton(bLinkMode,e);
        }
        private void bViewButton_MouseUp(object sender,System.Windows.Forms.MouseEventArgs e)
        {
            int incr = 0;
            if(e==null || e.Button==MouseButtons.Right)
                incr = -1;
            else if(e.Button==MouseButtons.Left)
                incr = 1;

            //	Get the button and the selected image index.
            Button but = (Button)sender;
            int ind = but.ImageIndex;

            //	Continue
            ind+=incr;
            if(ind>=but.ImageList.Images.Count)
                ind = 0;
            else if(ind<0)
                ind = but.ImageList.Images.Count-1;
            but.ImageIndex = ind;

            //	Continue
            but.Invalidate();
            Pb.Invalidate();
        }
        private void bViewButton_Paint(object sender,System.Windows.Forms.PaintEventArgs e)
        {
            PaintButton((Button)sender,e);
        }
        #endregion
		private static ImageCodecInfo GetEncoderInfo(string mimeType)
		{
			int j;
			ImageCodecInfo[] encoders;
			encoders = ImageCodecInfo.GetImageEncoders();
			for(j = 0; j < encoders.Length; ++j)
			{
				if(encoders[j].MimeType == mimeType)
					return encoders[j];
			}
			return null;
		}
        private void mJumpLastPath_Click(object sender,System.EventArgs e)
        {
            if(CurrentTool==ToolType.Polygon)
            {
                if(CurrentSelection.Po!=null)
                    this.ActivateSelection(CurrentSelection.Po.PreviousPoly,true);
            }
            else if(CurrentTool==ToolType.Contour)
            {
                if(CurrentSelection.Poly!=null)
                    this.ActivateSelection(CurrentSelection.Poly.PreviousContour,true);
            }
        }
        private void mJumpNextPath_Click(object sender,System.EventArgs e)
        {
            if(CurrentTool==ToolType.Polygon)
            {
                if(CurrentSelection.Po!=null)
                    this.ActivateSelection(CurrentSelection.Po.NextPoly,true);
            }
            else if(CurrentTool==ToolType.Contour)
            {
                if(CurrentSelection.Poly!=null)
                    this.ActivateSelection(CurrentSelection.Poly.NextContour,true);
            }
        }
		public ObjectParserData Opd;
		private void mSaveAs_Click(object sender, System.EventArgs e)
		{
			if(SfdSaveProject==null)
				SfdSaveProject = new SaveFileDialog();
            SfdSaveProject.SupportMultiDottedExtensions = true;
            SfdSaveProject.Filter = "Binary Format|*.ObjParser|XML Format|*.ObjParser.Xml|SOAP Format|*.ObjParser.Soap";
			SfdSaveProject.FileName = SaveName;
			if(SfdSaveProject.ShowDialog()==DialogResult.OK)
			{
				Cursor cur = Cursor.Current;
				Cursor.Current = Cursors.WaitCursor;

				SaveName = SfdSaveProject.FileName;
                if(SfdSaveProject.FilterIndex == 1)
                    Opd.LastSerializationType = SerializationType.Binary;
                else if(SfdSaveProject.FilterIndex == 2)
                {
                    Opd.LastSerializationType = SerializationType.Xml;
                    if(!SaveName.ToUpper().EndsWith(".OBJPARSER.XML"))
                        SaveName = SaveName + ".ObjParser.Xml";
                }
                else if(SfdSaveProject.FilterIndex == 3)
                    Opd.LastSerializationType = SerializationType.Soap;
                Opd.Serialize(SaveName, true, Opd.LastSerializationType);
				mSave.Enabled=true;
				this.Text = SaveName;

				Cursor.Current = cur;
			}
		}
		private void mSave_Click(object sender, System.EventArgs e)
		{
			Cursor cur = Cursor.Current;
			Cursor.Current = Cursors.WaitCursor;
			Opd.Serialize(Opd.Projname, true, Opd.LastSerializationType);
			Opd.RootCategory.ReclaimVertices();

			Cursor.Current = cur;
		}
		private void mFileNewProj_Click(object sender, System.EventArgs e)
		{
			if(OfdNewProjectFromImage==null)
				OfdNewProjectFromImage = new OpenFileDialog();
			OfdNewProjectFromImage.Filter = 
				"PNG |*.png|" + 
				"BMP |*.bmp|"+
				"GIF |*.gif|"+
				"JPEG |*.jpg|"+
				"TIFF |*.tif|"+
				"DCR |*.dcr";
			if(OfdNewProjectFromImage.ShowDialog()==DialogResult.OK)
			{
				string[] ss = OfdNewProjectFromImage.FileName.Split(new char[] {'.'});
				string projname = ss[0];
				for(int i=1; i<ss.Length-1; i++)
					projname = projname + ss[i];
				InitializeProject(projname, OfdNewProjectFromImage.FileName, null);
			}
		}
		private void mFileOpenProj_Click(object sender, System.EventArgs e)
		{
			if(ofdOpenProj==null)
				ofdOpenProj = new OpenFileDialog();
            ofdOpenProj.SupportMultiDottedExtensions = true;
			ofdOpenProj.Filter = "Binary Format|*.ObjParser|XML Format|*.ObjParser.Xml|SOAP Format|*.ObjParser.Soap";
			ofdOpenProj.FilterIndex = 1;
			if(ofdOpenProj.ShowDialog()==DialogResult.OK)
			{
                SerializationType stype = SerializationType.Unknown;
                if (ofdOpenProj.FilterIndex == 1)
                    stype = SerializationType.Binary;
                else if (ofdOpenProj.FilterIndex == 2)
                    stype = SerializationType.Xml;
                else if (ofdOpenProj.FilterIndex == 3)
                    stype = SerializationType.Soap;
				InitializeProject(stype, ofdOpenProj.FileName);
				mSave.Enabled = true;
			}
		}
		private void FormParse_Closing(object sender, System.ComponentModel.CancelEventArgs e)
		{
            // Display a MsgBox asking the user to save changes or abort.
            if(ProjectLoaded && MessageBox.Show("Close without saving?","Object Parser",MessageBoxButtons.YesNo) ==  DialogResult.No)
            {
                // Cancel the Closing event from closing the form.
                e.Cancel = true;
            }
		}
		private void mProjectClose_Click(object sender, System.EventArgs e)
		{
			this.Close();
		}
		private void mResetZoom_Click(object sender, System.EventArgs e)
		{
			InitZoom();
			Pb.Invalidate();
		}
		private void mBilinear_Click(object sender, System.EventArgs e)
		{
			if(!mBilinear.Checked)
			{
				mBilinear.Checked = true;
				mNearNeighbor.Checked = false;
				Pb.Invalidate();
			}
		}
		private void mNearNeighbor_Click(object sender, System.EventArgs e)
		{
			if(!mNearNeighbor.Checked)
			{
				mBilinear.Checked = false;
				mNearNeighbor.Checked = true;
				Pb.Invalidate();
			}
		}
		private void mTutorial_Click(object sender, System.EventArgs e)
		{
			System.Diagnostics.Process.Start(Application.StartupPath+"/../../Tutorial.doc");
		}
		private void mHelpKeyMouse_Click(object sender, System.EventArgs e)
		{
			System.Diagnostics.Process.Start(Application.StartupPath+"/../../KeyboardShortcuts.doc");
		}
		private void mSetDisplay_Click(object sender, System.EventArgs e)
		{
			OpenFileDialog ofd = new OpenFileDialog();
			ofd.Filter = 
				"PNG |*.png|"+
				"BMP |*.bmp|"+
				"GIF |*.gif|"+
				"JPEG |*.jpg|"+
				"TIFF |*.tif|"+
				"DCR |*.dcr";
			if(ofd.ShowDialog()==DialogResult.OK)
			{
				Cursor last = Cursor.Current;
				try
				{	
					Cursor.Current = Cursors.WaitCursor;
                    DisplayBmp = Bmp = new Bitmap(ofd.FileName);
                    if (Bmp.PixelFormat != PixelFormat.Format32bppArgb)
                        DisplayBmp = Bmp = Bmp.Clone(new Rectangle(0, 0, Bmp.Width, Bmp.Height), PixelFormat.Format32bppArgb);
					Opd.DisplayImagename = ofd.FileName;
					Pb.Invalidate();
				}
				catch
				{
					MessageBox.Show("The file " + ofd.FileName + " could not be opened.", "Display image was not reset from "+Opd.DisplayImagename+".");
				}
				finally
				{
					Cursor.Current = last;
				}
			}
		}
		private void mSetCore_Click(object sender, System.EventArgs e)
		{
			OpenFileDialog ofd = new OpenFileDialog();
			ofd.Filter = 
				"PNG |*.png|"+
				"BMP |*.bmp|"+
				"GIF |*.gif|"+
				"JPEG |*.jpg|"+
				"TIFF |*.tif|"+
				"DCR |*.dcr";
			if(Opd != null && Opd.Imagename != null)
				ofd.FileName = Opd.Imagename;
			if(ofd.ShowDialog()==DialogResult.OK)
			{
				Cursor last = Cursor.Current;
				try
				{	
					Cursor.Current = Cursors.WaitCursor;
					if(Opd.DisplayImagename==null)
						Opd.DisplayImagename=Opd.Imagename;
					if(Bmp==null)
						Bmp = new Bitmap(ofd.FileName);
					if(Opd.Imagename!=ofd.FileName)
					{
						if(this.CorePixels!=null)
						{
							CorePixels = null;
							CorePixelsFloat = null;
						}
						else if(this.CorePixelsFloat!=null)
						{
							CorePixelsFloat = null;
						}
					}
					Opd.Imagename = ofd.FileName;
				}
				catch
				{
					MessageBox.Show("The file " + ofd.FileName + " could not be opened.", "Core image was not reset from "+Opd.Imagename+".");
				}
				finally
				{
					Cursor.Current = last;
				}
			}
		}
        /*
		private void mCircles_Click(object sender, System.EventArgs e)
		{
			CircleDialog cd = new CircleDialog(this, Opd.Circles);
			if(DialogResult.OK == cd.ShowDialog())
			{
				Opd.Circles = cd.Circles;
				Opd.ActiveCircleInd = cd.ActiveInd;
				Pb.Invalidate();
			}
		}
		private void mLockCircle_Click(object sender, System.EventArgs e)
		{
			mLockCircle.Checked = !mLockCircle.Checked;
		}
        */
		private void mMaximize_Click(object sender, System.EventArgs e)
		{
			this.SuspendLayout();
			this.Left = 0;
			this.Top = 0;
			this.Size = Screen.GetBounds(this).Size;
			this.Height -= 36;
			this.ResumeLayout();
		}
		private void mCopyZoomed_Click(object sender, System.EventArgs e)
		{
			Bitmap bmp = new Bitmap(Pb.Width, Pb.Height);
			Graphics g = Graphics.FromImage(bmp);
			PaintEventArgs p = new PaintEventArgs(g, new Rectangle(0,0,Pb.Width,Pb.Height));
			Pb_Paint(this, p);
			Clipboard.SetDataObject(bmp);
		}
		private void mCopyActiveObj_Click(object sender, System.EventArgs e)
		{
			Clipboard.SetDataObject(Opd.ActiveObject.GetBitmap32(this.Bmp));
		}
		private void mCopyBgActiveObj_Click(object sender, System.EventArgs e)
		{
			Clipboard.SetDataObject(Opd.ActiveObject.GetBackgroundBitmap32(this.Bmp));
		}
		private void mCopyActiveObjWithBg_Click(object sender, System.EventArgs e)
		{
			Clipboard.SetDataObject(Opd.ActiveObject.GetBoundingBitmap32(this.Bmp));
		}
		private void mResetPixels_Click(object sender, System.EventArgs e)
		{
			Cursor oldCursor = Cursor.Current;
			Cursor.Current = Cursors.WaitCursor;

			Opd.RootCategory.ResetPixelTagger();
			this.BmpCurrentObj = new Bitmap(this.BmpCurrentObj.Width, this.BmpCurrentObj.Height);
			this.BmpNonObj = new Bitmap(this.BmpNonObj.Width, this.BmpNonObj.Height);
			this.BmpOtherObj = new Bitmap(this.BmpOtherObj.Width, this.BmpOtherObj.Height);
			SelectionRecord.PaintBitmaps(Opd.RootCategory,CurrentSelection,this);

			Pb.Invalidate();
			Cursor.Current = oldCursor;
		}
		/// <summary>
		/// Activates an object and centers view over that object.
		/// Adds the appropriate macro to the undo stack.
		/// </summary>
		/// <param name="po"></param>
		/// <param name="extraRoom">1 (lowest acceptable value) gives 1 bounding rect.  2 gives 2 bounding rects.  4 gives 4 bounding rects.  etc.</param>
		/// <param name="activate">if true, the object is activated and an Undo macro is recorded for the activation.
		/// if false, then this just centers the view over the object.</param>
		/// <param name="zoomIn">If true, then this function can zoom inwards.
		/// If false, then this function cannot zoom inwards.  The function can always zoom
		/// outwards, as needed, in order to encompass the object with extraRoom.</param>
		public void ViewAndActivate(object obj, int extraRoom, bool activate, bool zoomIn)
		{
			ParsedObject po = Opd.ActiveObject;

			//	Switch active object and encode a new macro into the Undo list.
			if(activate)
				ActivateSelection(obj, true);
			else
			{
				if( obj.GetType()==typeof(CategoryNode) )
					po = ((CategoryNode)obj).ActiveObject;
				else if( obj.GetType()==typeof(ParsedObject) )
					po = (ParsedObject)obj;
				else if( obj.GetType()==typeof(PolygonF) )
					po = ((PolygonF)obj).Owner;
				else if( obj.GetType()==typeof(ContourF) )
					po = ((ContourF)obj).Owner;
			}

			//	Zoom barely encompasses po.BoundingRect.
			if(extraRoom<1)
				extraRoom=1;
			Rectangle rect = po.BoundingRect;
			if(rect.Width > 1 && rect.Height > 1)
			{
				int x = rect.X + rect.Width/2;
				int y = rect.Y + rect.Height/2;
				Rectangle rect2 = new Rectangle(
					x-rect.Width/2*extraRoom, y-rect.Height/2*extraRoom,
					rect.Width*extraRoom, rect.Height*extraRoom );
				if(!zoomIn && (this.ImgRect.Height>=rect2.Height||this.ImgRect.Width>=rect2.Width) )
				{
					rect2 = new Rectangle(
						(int)(0.5f+x-ImgRect.Width/2.0f), (int)(0.5f+y-ImgRect.Height/2.0f),
						(int)(0.5f+ImgRect.Width), (int)(0.5f+ImgRect.Height) );
				}
				InitZoom(rect2);
				Pb.Invalidate();
			}
		}
		public FormCategorize FormCat;
		private void mCategorize_Click(object sender, System.EventArgs e)
		{
			if(FormCat != null)
				FormCat.Close();
			FormCat = new FormCategorize(this, typeof(ObjectCategorizationData), null);
			FormCat.Activate();
			FormCat.Show();
		}
		private void mCategorizeContours_Click(object sender, System.EventArgs e)
		{
			if(FormCat != null)
				FormCat.Close();
			FormCat = new FormCategorize(this, typeof(ContourCategorizationData), null);
			FormCat.Activate();
			FormCat.Show();
		}
		/// <summary>
		/// Changed the ObjParser files from one version to another.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void mFix1_Click(object sender, System.EventArgs e)
		{
			
			if(OfdBatchFix==null)
				OfdBatchFix = new OpenFileDialog();
			OfdBatchFix.Title = "Please select the ObjParser files for Batch Fix #1.";
			OfdBatchFix.Multiselect = true;
			OfdBatchFix.Filter = "ObjParser files|*.ObjParser";
			if(OfdBatchFix.ShowDialog(this)==DialogResult.OK)
			{
				string directory = OfdBatchFix.FileName;
				if(directory != null && directory.Length>0)
				{
					int j;
					for(j=directory.Length-1; j>=0; j--)
						if(directory[j]=='/' || directory[j]=='\\')
						{
							directory = directory.Substring(0, j);
							break;
						}
					if(Directory.Exists(directory))
					{
						DirectoryInfo di = new DirectoryInfo(directory);
						int k = directory.Length-1;
						while(k>0)
							if(directory[--k]=='/' || directory[k]=='\\')
								break;
						string dirMinor = directory.Substring(0, k+1);
						DirectoryInfo diCore = new DirectoryInfo(dirMinor + "CoreImages");
						DirectoryInfo diDisplay = new DirectoryInfo(dirMinor + "DisplayImages");

						FileInfo fi;

						Cursor.Current = Cursors.WaitCursor;

						//	Change the *.ObjParser files
						int i;
						for(i=0; i<OfdBatchFix.FileNames.Length; i++)
						{
							fi = new FileInfo(OfdBatchFix.FileNames[i]);
							string[] oldNames = fi.Name.Split('/', '\\');
							string fname = oldNames[oldNames.Length-1];
							statusBar1.Text = "Duplicating " + fi.Name + " as " + fi.Name + ".Old";
							fi.CopyTo(fi.Name+".Old", true);
							statusBar1.Text = "Opening " + fi.Name + ".";
                            ObjectParserData opd = ObjectParserData.Deserialize(fi.FullName, this, SerializationType.Binary);

							//	Set the core image.
							string[] oldCore = opd.Imagename.Split('/', '\\');
							opd.Imagename = "..\\CoreImages\\" +
								oldCore[oldCore.Length-1].Replace(".8", "_8").Replace(".12", "_12");

							//	Set the display image.
							if(opd.DisplayImagename != null && opd.DisplayImagename.Length>0)
							{	
								string[] oldDisplay = opd.DisplayImagename.Split('/', '\\');
								opd.DisplayImagename = "..\\DisplayImages\\" +
									oldDisplay[oldDisplay.Length-1].Replace(".8", "_8").Replace(".12", "_12");
							}
							
							//	Save the file.
							opd.AbsolutizeImageNames();
                            opd.Serialize(opd.Projname, true, SerializationType.Binary);
							statusBar1.Text = "Finished " + fi.Name + ".";
						}

						//	Change the image files.
						FileInfo[] fis = diCore.GetFiles();
						for(i=0; i<fis.Length; i++)
						{
							string name = fis[i].FullName.Replace(".12", "_12").Replace(".8", "_8");
							if( fis[i].FullName!=name)
							{
								statusBar1.Text = "Renaming " + fis[i].Name + " as " + name + ".";
								File.Copy( fis[i].FullName, name, true );
								File.Delete( fis[i].FullName );
							}
						}

						//	Change the image fisles.
						fis = diDisplay.GetFiles();
						for(i=0; i<fis.Length; i++)
						{
							string name = fis[i].FullName.Replace(".12", "_12").Replace(".8", "_8");
							if( fis[i].FullName!=name)
							{
								statusBar1.Text = "Renaming " + fis[i].Name + " as " + name + ".";
								File.Copy( fis[i].FullName, name, true );
								File.Delete( fis[i].FullName );
							}
						}

						statusBar1.Text = "Ready.";

						Cursor.Current = Cursors.Default;
					}
				}
			}
		}
        private void mBatchFix2_Click(object sender,EventArgs e)
        {
            if(OfdBatchFix==null)
                OfdBatchFix = new OpenFileDialog();
            OfdBatchFix.Title = "Please select the ObjParser files for Batch Fix #2.";
            OfdBatchFix.Multiselect = true;
            OfdBatchFix.Filter = "ObjParser files|*.ObjParser";
            if(OfdBatchFix.ShowDialog(this)==DialogResult.OK)
            {
                /*
                string directory = OfdBatchFix.FileName;
                if(directory != null && directory.Length>0)
                {
                    int j;
                    for(j=directory.Length-1;j>=0;j--)
                        if(directory[j]=='/' || directory[j]=='\\')
                        {
                            directory = directory.Substring(0,j);
                            break;
                        }
                    if(Directory.Exists(directory))
                    {
                        DirectoryInfo di = new DirectoryInfo(directory);
                        int k = directory.Length-1;
                        while(k>0)
                            if(directory[--k]=='/' || directory[k]=='\\')
                                break;
                        string dirMinor = directory.Substring(0,k+1);
                        DirectoryInfo diCore = new DirectoryInfo(dirMinor + "CoreImages");
                        DirectoryInfo diDisplay = new DirectoryInfo(dirMinor + "DisplayImages");
                    }
                }
                */
                FileInfo fi;

                Cursor.Current = Cursors.WaitCursor;

                if(Rtb==null || Rtb.IsDisposed)
                    Rtb = new FormRtb();
                Rtb.Show();
                EdgeGroupArray ega;
                Edge ed;
                ObjectParserData opd;

                //	Change the *.ObjParser files
                int i;
                for(i=0;i<OfdBatchFix.FileNames.Length;i++)
                {
                    fi = new FileInfo(OfdBatchFix.FileNames[i]);
                    string[] oldNames = fi.Name.Split('/','\\');
                    string fname = oldNames[oldNames.Length-1];
                    statusBar1.Text = "Duplicating " + fi.Name + " as " + fi.Name + ".Old";
                    fi.CopyTo(fi.Name+".Old",true);
                    statusBar1.Text = "Opening " + fi.Name + ".";
                    opd = ObjectParserData.Deserialize(fi.FullName,this,SerializationType.Binary);
                    //  BLAH
                    ega = opd.RootCategory.AfterChange_ValidateEdges();
                    Rtb.Rtb.AppendText("\n"+ega.Count.ToString()+"  ===========  " + fi.Name);
                    Rtb.Rtb.AppendText("\nEDGES REMOVED:\n-------------------------");
                    for(int j=0;j<ega.Count;j++)
                    {
                        ed = ega[j].DominantEdge;
                        if(ed!=null)
                            Rtb.Rtb.AppendText("\n\t" + ed.ToString());

                    }
                    opd.Serialize(opd.Projname,false,SerializationType.Binary);
                    Rtb.Rtb.AppendText("\n----------------------");
                    statusBar1.Text = "Finished " + fi.Name + ".";
                }

                statusBar1.Text = "Ready.";

                Cursor.Current = Cursors.Default;
            }
        }
        private void mBatchBinaryToXml_Click(object sender,EventArgs e)
        {
            if(OfdBatchFix==null)
                OfdBatchFix = new OpenFileDialog();
            OfdBatchFix.Title = "Please select the ObjParser files for saving in XML format.";
            OfdBatchFix.Multiselect = true;
            OfdBatchFix.Filter = "ObjParser files|*.ObjParser";
            if(OfdBatchFix.ShowDialog(this)==DialogResult.OK)
            {
                //	Change the *.ObjParser files
                int i;
                FileInfo fi;
                for(i=0;i<OfdBatchFix.FileNames.Length;i++)
                {
                    fi = new FileInfo(OfdBatchFix.FileNames[i]);
                    statusBar1.Text = "Opening " + fi.Name + ".";
                    ObjectParserData opd = ObjectParserData.Deserialize(fi.FullName,this,SerializationType.Binary);
                    opd.Serialize(opd.Projname + ".Xml",false,SerializationType.Xml);
                    statusBar1.Text = "Finished " + fi.Name + ".";
                }

                statusBar1.Text = "Ready.";

                Cursor.Current = Cursors.Default;
            }
        }
		private void mImportAttributes_Click(object sender, System.EventArgs e)
		{
			if(OfdImportAttributesOpd==null)
				OfdImportAttributesOpd = new OpenFileDialog();
			if(OfdImportAttributesTxt==null)
				OfdImportAttributesTxt = new OpenFileDialog();

			OpenFileDialog ofdOpd = OfdImportAttributesOpd;
			OpenFileDialog ofdTxt = OfdImportAttributesTxt;

			ofdOpd.Title = "Select the ObjParser files.";
			ofdOpd.Filter = "ObjectParser Binary Format|*.ObjParser";
			ofdOpd.Multiselect = true;
			ofdOpd.CheckFileExists = true;
			if(ofdOpd.ShowDialog() == DialogResult.OK)
			{
				ofdTxt.Title = "Select the attributes file.";
				ofdTxt.Filter = "";
				ofdTxt.Multiselect = false;
				ofdTxt.CheckFileExists = true;
				if(ofdTxt.ShowDialog() == DialogResult.OK)
				{
					ArrayList log;
					this.statusBar1.Text = "Loading Attributes...";
					ObjectParserData.LoadAttributes(ofdOpd.FileNames, ofdTxt.FileName, out log);
					this.statusBar1.Text = "Ready.";
					FormRtb report = new FormRtb();
					
					string[] lines = new string[log.Count];
					for(int i=0; i<lines.Length; i++)
						lines[i] = (string)log[i];
					
					report.Rtb.Lines = lines;
					report.Activate();
					report.Show();
				}
			}
		}
		private void mCategorizationValues_Click(object sender, System.EventArgs e)
		{
			ProjPropertiesDialog ppd = new ProjPropertiesDialog(Opd);
			if(DialogResult.OK==ppd.ShowDialog())
				this.mSave.Enabled = true;
		}
		private void mImageSettings_Click(object sender, System.EventArgs e)
		{
			FormImageSettings fcs = new FormImageSettings(Opd);
			fcs.ShowDialog();
			this.mSave.Enabled = true;
		}
		private void mFindBadVert_Click(object sender, System.EventArgs e)
		{
			PolygonFarray polys = new PolygonFarray();
			Opd.RootCategory.FindUnstandardizedPolygons(polys);
			string txt = "";
			for(int i=0; i<polys.Count; i++)
			{
				txt=txt+ Convert.ToString(polys[i].Owner.Polygons.IndexOf(polys[i]))
					+ "\t\t" + Convert.ToString(polys[i].Owner.Category.Objects.IndexOf(polys[i].Owner))
					+ "\t\t" + polys[i].Owner.Name
					+ "\t\t" + polys[i].Owner.Category.Name + '\n';
			}
			FormRtb rtb = new FormRtb(txt);
			rtb.Activate();
			rtb.Show();
		}
		private void mElimRedundant_Click(object sender, System.EventArgs e)
		{
			int nElim = Opd.RootCategory.EliminateRedundantVertices();
			if(nElim>0)
				MessageBox.Show(this, Convert.ToString(nElim) + " vertices eliminated.");
		}
		private void mSeriesBackward_Click(object sender, System.EventArgs e)
		{
			if(!Tv.ContainsFocus)
			{
				Tv.Focus();
				TreeNode tn = NodeAttachedTo(Opd.ActiveThing);
				if(tn!=null)
				{
					tn.EnsureVisible();
					tn = tn.PrevNode;
				}
				if(tn!=null)
				{
					Tv.SelectedNode = tn;
					if(Opd.ActiveObject!=null)
						this.ViewAndActivate(Opd.ActiveObject, 4, false, false);
				}
			}
		}
		private void mSeriesForward_Click(object sender, System.EventArgs e)
		{
			if(!Tv.ContainsFocus)
			{
				Tv.Focus();
				TreeNode tn = NodeAttachedTo(Opd.ActiveThing);
				if(tn!=null)
				{
					tn.EnsureVisible();
					tn = tn.NextNode;
				}
				if(tn!=null)
				{
					tn.EnsureVisible();
                    Tv.SelectedNode = tn;
					if(Opd.ActiveObject!=null)
						this.ViewAndActivate(Opd.ActiveObject, 3, false, false);
				}
			}
		}
		private void mElimEmpty_Click(object sender, System.EventArgs e)
		{
			Opd.RootCategory.RemoveEmptyPolygonsAndObjects();
		}
		private void mFilterTextToBinary_Click(object sender, System.EventArgs e)
		{
			if(OfdFilter==null)
				OfdFilter = new OpenFileDialog();
			OpenFileDialog ofd = OfdFilter;
			ofd.Title = "Please select the text files for filter extraction.";
			ofd.Multiselect = true;
			ofd.Filter = "All Files|*.*";
			if(ofd.ShowDialog(this)==DialogResult.OK)
			{
				int i=0;
				try
				{
					for(i=0; i<ofd.FileNames.Length; i++)
					{
						FilterResponseList frl = FilterResponseList.FromTextFile(ofd.FileNames[i]);
						frl.SerializeBinary(ofd.FileNames[i] + ".FilterResponseList");
					}
				}
				catch(Exception ex)
				{
					MessageBox.Show(this,
						"Text file conversion process has halted because there was a problem "+
						"with "+ ofd.FileNames[i] + ".  " + ex.Message);
				}
			}
		}
		private void mTidyOwnedEdges_Click(object sender, System.EventArgs e)
		{
			Opd.TidyOwnedEdges();
			Pb.Invalidate();
		}
		private void FormParse_Resize(object sender, System.EventArgs e)
		{
			panelRight.Width = panelMain.Width-panelLeft.Width-splitMainVert.Width;
		}
		private void splitMainVert_SplitterMoving(object sender, System.Windows.Forms.SplitterEventArgs e)
		{
			panelRight.Left = splitMainVert.Right;
			panelRight.Width = this.Right-panelRight.Left-1;
		}
		private void splitMainVert_SplitterMoved(object sender, System.Windows.Forms.SplitterEventArgs e)
		{
			panelRight.Left = splitMainVert.Right;
			panelRight.Width = this.Right-panelRight.Left-1;
		}
		private void cmViewEdgePoints_Click(object sender, System.EventArgs e)
		{
			ArrayList pts = new ArrayList();
			CategoryNode cn = Opd.ActiveCategory;
			if(cn!=null)
			{
				cn.EdgePoints(1.0f, pts);
			}
			Pen pen = new Pen(Color.FromArgb(0,255,0), 3.0f);
			PointF[] pfa;
			Graphics g = this.Pb.CreateGraphics();
			for(int i=0; i<pts.Count; i++)
			{
				pfa = (PointF[])pts[i];
				if(pfa!=null && pfa.Length>1)
				{
					this.ImgToPb(pfa);
					g.DrawLines(pen, pfa);
				}
			}
		}
		private void mBatchEdgesOut_Click(object sender, System.EventArgs e)
		{
			int j,k;
			PointF[] pts;
			if(OfdBatch==null)
				OfdBatch = new OpenFileDialog();
			OfdBatch.Multiselect = true;
			OfdBatch.Filter = "ObjParser Files | *.ObjParser";
			if(OfdBatch.ShowDialog()==DialogResult.OK)
			{
				string[] fnames = OfdBatch.FileNames;
				if(fnames != null)
				{
					for(int i=0; i<fnames.Length; i++)
					{
                        ObjectParserData opd = ObjectParserData.Deserialize(fnames[i], this, SerializationType.Binary);
						ArrayList edges = new ArrayList();
						opd.RootCategory.EdgePoints(1.0f, edges);

						statusBar1.Text = opd.ShortProjname;

						FileStream txtFile
							= new FileStream(fnames[i].Replace(".ObjParser", ".txt"), FileMode.Create);
						StreamWriter sw = new StreamWriter(txtFile);

						for(j=0; j<edges.Count; j++)
						{
							pts = (PointF[])edges[j];
							for(k=0; k<pts.Length; k++)
								sw.WriteLine("  "+Convert.ToString(pts[k].X)+"    "+Convert.ToString(pts[k].Y));
						}							
						sw.Close();
					}
				}
			}
			this.statusBar1.Text = "Ready.";
		}
		private void FormParse_Load(object sender, System.EventArgs e)
		{
			UpdatePbSize();
		}
		public void UpdatePbSize()
		{
			this.Pb.SuspendLayout();
			this.PbRibbon.SuspendLayout();

			this.PbRibbon.Top = splitRightHor.Bottom;
			this.PbRibbon.Left = 0;
			this.PbRibbon.Height = this.panelRight.Bottom-this.splitRightHor.Bottom;
			this.PbRibbon.Width = this.panelRight.Right-this.splitMainVert.Right;

			this.PbRibbon.ResumeLayout();

			this.Pb.Top = 0;
			this.Pb.Left = 0;
			this.Pb.Height = this.splitRightHor.Top-this.Pb.Top;
			this.Pb.Width = this.panelRight.Right-this.splitMainVert.Right;

			this.Pb.ResumeLayout();

			if(ActiveSurfaces!=null && ActiveSurfaces.Painter!=null)
			{
				//ActiveSurfaces.Painter.ViewerRect=new RectangleF(0.0f,0.0f,PbRibbon.Width,PbRibbon.Height);
				PbRibbon.InitZoom(ActiveSurfaces.Painter.NaturalRect);
				ActiveSurfaces.Painter.PbSize=PbRibbon.Size;
				ActiveSurfaces_UpdateView();
				PbRibbon.Invalidate();
			}
		}
		private void panelRight_SizeChanged(object sender, System.EventArgs e)
		{
			UpdatePbSize();
		}
		public static void PaintButton(Button but, PaintEventArgs e)
		{
			if(but.ImageList!=null)
				e.Graphics.DrawImage(but.ImageList.Images[but.ImageIndex], 0, 0, but.Width, but.Height);
			else if(but.Image!=null)
				e.Graphics.DrawImage(but.Image, 0, 0, but.Width, but.Height);
		}
		public FormLogGabor Flg=null;
		private void mLogGabor_Click(object sender, System.EventArgs e)
		{
			if(Flg==null || Flg.IsDisposed)
			{
				Flg = new FormLogGabor(this);
				Flg.TopMost = false;
			}
			Flg.Activate();
			Flg.Show();
			Flg.TopMost = false;
		}
		private void mUnswallowAll_Click(object sender, System.EventArgs e)
		{
			PolygonF pf = Opd.ActivePoly;
			if(pf!=null)
				pf.Swallowed.Clear();
		}
		public void SetStatusBar(string text)
		{
			this.statusBar1.Text = text;
			this.statusBar1.Refresh();
		}
		private void mViewNan_Click(object sender, System.EventArgs e)
		{
			mViewNan.Checked = !mViewNan.Checked;
			if(mViewNan.Checked)
			{
				if(NanBmp==null)
					this.LoadNanBitmap();
				Bmp=NanBmp;
			}
			else
				Bmp=DisplayBmp;
			Pb.Invalidate();
		}
		public static int NumSharedStartingCharacters(string a, string b)
		{
			int output = 0;
			while( output<a.Length && output<b.Length && a[output]==b[output] )
				output++;
			return output;
		}
		private void mImportCameraSettings_Click(object sender, System.EventArgs e)
		{
			if(this.OfdOpenBatch.ShowDialog()==DialogResult.OK)
			{
				string[] opdFiles = this.OfdOpenBatch.FileNames;
				if(this.OfdCameraSettings.ShowDialog()==DialogResult.OK)
				{
					string[] a, b;

					FormRtb logOut = new FormRtb("Log for import of camera settings:\n\n");
					if(logOut.Width<500)
						logOut.Width=500;
					logOut.Activate();
					logOut.Show();

					string[] tfsFiles = this.OfdCameraSettings.FileNames;
					int iOpd, iTfs, maxTfs, imaxTfs, tryTfs;
					for( iOpd=0; iOpd<opdFiles.Length; iOpd++ )
					{
						a = opdFiles[iOpd].Split('/', '\\');
						b = tfsFiles[0].Split('/', '\\');
						maxTfs = NumSharedStartingCharacters(a[a.Length-1],b[b.Length-1]);
						imaxTfs = 0;
						for( iTfs=1; iTfs<tfsFiles.Length; iTfs++)
						{
							b = tfsFiles[iTfs].Split('/', '\\');
							tryTfs = NumSharedStartingCharacters(a[a.Length-1],b[b.Length-1]);
							if( tryTfs > maxTfs )
							{
								maxTfs = tryTfs;
								imaxTfs = iTfs;
							}
						}

                        ObjectParserData opd = ObjectParserData.Deserialize(opdFiles[iOpd], null, SerializationType.Binary);
						logOut.Rtb.AppendText(opdFiles[iOpd]);
						logOut.Rtb.Invalidate();
						logOut.Rtb.Refresh();

						StreamReader sr = File.OpenText(tfsFiles[imaxTfs]);
						opd.ShutterRate = 1.0f / Convert.ToSingle(sr.ReadLine());
						opd.Fstop = Convert.ToSingle(sr.ReadLine());
						opd.IsoFilmSpeed = Convert.ToSingle(sr.ReadLine());
						sr.Close();

						logOut.Rtb.AppendText("\t--\t" + tfsFiles[imaxTfs]);
						logOut.Rtb.Invalidate();
						logOut.Rtb.Refresh();

                        opd.Serialize(opd.Projname, false, SerializationType.Binary);

						logOut.Rtb.AppendText("\t--\tsaved\n");
						logOut.Rtb.Invalidate();
						logOut.Rtb.Refresh();
					}
				}
			}
		}
        private void mAbout_Click(object sender,EventArgs e)
        {
            MessageBox.Show(
                "This software was created by Almon David Ing\nfor use at the Center for Perceptual Systems\nat the University of Texas at Austin."
                +"\n\nThis software is free for organizations pursuing\nnon-profit scientific research.  All other organizations"
                +"\nmust get prior approval in writing or their\nObjectParser data will become property of the\nCenter for Perceptual Systems at UT Austin.", 
                "ObjectParser usage rights");
        }
        private void pbTool_Paint(object sender,PaintEventArgs e)
        {
            if(CurrentTool==ToolType.None)
                e.Graphics.DrawImage(imTool.Images[0],0,0);
            else if(CurrentTool==ToolType.Polygon)
                e.Graphics.DrawImage(imTool.Images[1],0,0);
            else if(CurrentTool==ToolType.Contour)
                e.Graphics.DrawImage(imTool.Images[2],0,0);
            else if(CurrentTool==ToolType.Circle)
                e.Graphics.DrawImage(imTool.Images[3],0,0);
        }
        private void mPaintShadowsYellow_Click(object sender,EventArgs e)
        {
            if(OfdBatchFix==null)
                OfdBatchFix = new OpenFileDialog();
            OfdBatchFix.Title = "Please select the ObjParser files for Paint Shadows Yellow.";
            OfdBatchFix.Multiselect = true;
            OfdBatchFix.Filter = "ObjParser files|*.ObjParser";
            if(OfdBatchFix.ShowDialog(this)==DialogResult.OK)
            {
                string directory = OfdBatchFix.FileName;
                if(directory != null && directory.Length>0)
                {
                    int j;
                    for(j=directory.Length-1;j>=0;j--)
                        if(directory[j]=='/' || directory[j]=='\\')
                        {
                            directory = directory.Substring(0,j);
                            break;
                        }
                    if(Directory.Exists(directory))
                    {
                        DirectoryInfo di = new DirectoryInfo(directory);
                        int k = directory.Length-1;
                        while(k>0)
                            if(directory[--k]=='/' || directory[k]=='\\')
                                break;
                        string dirMinor = directory.Substring(0,k+1);
                        DirectoryInfo diCore = new DirectoryInfo(dirMinor + "CoreImages");
                        DirectoryInfo diDisplay = new DirectoryInfo(dirMinor + "DisplayImages");

                        FileInfo fi;

                        Cursor.Current = Cursors.WaitCursor;

                        //	Change the *.ObjParser files
                        int i;
                        for(i=0;i<OfdBatchFix.FileNames.Length;i++)
                        {
                            fi = new FileInfo(OfdBatchFix.FileNames[i]);
                            string[] oldNames = fi.Name.Split('/','\\');
                            string fname = oldNames[oldNames.Length-1];
                            statusBar1.Text = "Duplicating " + fi.Name + " as " + fi.Name + ".Old";
                            fi.CopyTo(fi.Name+".Old",true);
                            statusBar1.Text = "Opening " + fi.Name + ".";
                            ObjectParserData opd = ObjectParserData.Deserialize(fi.FullName,this,SerializationType.Binary);
                            opd.RootCategory.PaintShadows(true,Color.Yellow);
                            opd.Serialize(opd.Projname,false,SerializationType.Binary);
                            statusBar1.Text = "Finished " + fi.Name + ".";
                        }

                        statusBar1.Text = "Ready.";

                        Cursor.Current = Cursors.Default;
                    }
                }
            }
        }
	}
}
